2013-10-02 8 views
5

Dies mag ein Duplikat sein, aber ich habe mir hier viele andere Fragen angeschaut und sie vermissen gewöhnlich, wonach ich suche. Sie sprechen meist von einem Service, den sie selbst geschaffen haben. Das kann und habe ich getan. Ich versuche zu überschätzen, was eckig mit meinem Spott spritzt. Ich dachte, es wäre das gleiche, aber aus irgendeinem Grund, wenn ich durch den Code gehe, ist es immer der eckige $ cookieStore und nicht mein Spott.Wie spotze ich einen Angular Service mit Jasmin?

Ich habe sehr begrenzte Erfahrung mit Jasmin und angularjs. Ich komme von einem C# Hintergrund. Ich schreibe normalerweise Komponententests moq (Mocking Framework für C#). Ich verwende etwas wie dieses

[TestClass] 
public PageControllerTests 
{ 
    private Mock<ICookieStore> mockCookieStore; 
    private PageController controller; 

    [TestInitialize] 
    public void SetUp() 
    { 
     mockCookieStore = new Mock<ICookieStore>(); 
     controller = new PageController(mockCookieStore.Object); 
    } 

    [TestMethod] 
    public void GetsCarsFromCookieStore() 
    { 
     // Arrange 
     mockCookieStore.Setup(cs => cs.Get("cars")) 
        .Return(0); 

     // Act 
     controller.SomeMethod(); 

     // Assert 
     mockCookieStore.VerifyAll(); 
    } 
} 

ich verspotten wollen die $ cookieStore Service zu sehen, die ich in einem meiner Controller verwenden.

app.controller('PageController', ['$scope', '$cookieStore', function($scope, $cookieStore) { 

    $scope.cars = $cookieStore.get('cars'); 

    if($scope.cars == 0) { 
      // Do other logic here 
      . 
    } 

    $scope.foo = function() { 
     . 
     . 
    } 
}]); 

Ich möchte sicherstellen, dass die $ cookieStore.get Methode mit einer ‚Garage‘ Argument aufgerufen wird. Ich möchte auch kontrollieren können, was es zurückgibt. Ich möchte es 0 zurückgeben und dann muss mein Controller eine andere Logik machen.

Hier ist mein Test.

describe('Controller: PageController', function() { 

    var controller, 
     scope, 
     cookieStoreSpy; 

    beforeEach(function() { 
     cookieStoreSpy = jasmine.createSpyObj('CookieStore', ['get']); 
     cookieStoreSpy.get.andReturn(function(key) { 
      switch (key) { 
       case 'cars': 
        return 0; 
       case 'bikes': 
        return 1; 
       case 'garage': 
        return { cars: 0, bikes: 1 }; 
      } 
     }); 

     module(function($provide) { 
      $provide.value('$cookieStore', cookieStoreSpy); 
     }); 
     module('App'); 

    }); 

    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) { 
     scope = $rootScope.$new(); 
     controller = $controller; 
    })); 

    it('Gets car from cookie', function() { 
     controller('PageController', { $scope: scope }); 
     expect(cookieStoreSpy.get).toHaveBeenCalledWith('cars'); 
    }); 
}); 

Antwort

5

Dies ist eine Lösung für die Diskussion w Das hatte ich in meiner vorherigen Antwort.

In meinem Controller verwende ich $ location.path und $ location.search. So um die $ Lage mit meinem Mock überschreibt ich getan habe:

locationMock = jasmine.createSpyObj('location', ['path', 'search']); 
locationMock.location = ""; 

locationMock.path.andCallFake(function(path) { 
    console.log("### Using location set"); 
    if (typeof path != "undefined") { 
    console.log("### Setting location: " + path); 
    this.location = path; 
    } 

    return this.location; 
}); 

locationMock.search.andCallFake(function(query) { 
    console.log("### Using location search mock"); 
    if (typeof query != "undefined") { 
    console.log("### Setting search location: " + JSON.stringify(query)); 
    this.location = JSON.stringify(query); 
    } 

    return this.location; 
}); 

module(function($provide) { 
    $provide.value('$location', locationMock); 
}); 

ich nichts in dem $ Controller zu injizieren habe. Es hat einfach funktioniert.Schauen Sie sich die Protokolle:

LOG: '### Mit Standort Set'

LOG: '### Einstellung Standort:/test'

LOG: ‚### Mit Standortsuche Mock '

LOG:' ### Einstellen des Suchorts: {"limit": "50", "q": "ani", "Tags": [1,2], "Kategorie_ID": 5} '

+0

+1 Danke für die Mühe. und Ort ist der nächste, den ich brauchte :) Lass dich wissen, ob es funktioniert hat. – uriDium

0

Wenn Sie die Argumente überprüfen möchten, Spion auf der Methode

// declare the cookieStoreMock globally 
var cookieStoreMock; 

beforeEach(function() { 
    cookieStoreMock = {}; 

    cookieStoreMock.get = jasmine.createSpy("cookieStore.get() spy").andCallFake(function(key) { 
    switch (key) { 
     case 'cars': 
     return 0; 
     case 'bikes': 
     return 1; 
     case 'garage': 
     return { 
      cars: 0, 
      bikes: 1 
     }; 
    } 
    }); 

    module(function($provide) { 
    $provide.value('cookieStore', cookieStoreMock); 
    }); 
}); 

Und dann das Argument testen tun

expect(searchServiceMock.search).toHaveBeenCalledWith('cars'); 
+0

Habe ich das nicht getan. Bitte schau dir meinen Test an. Ich bin mir sicher, dass ich das tue. Ich fragte auch, wie ich meinen Mock spritzen und nicht wie ich einen erstellen soll. – uriDium

+0

Aber Sie injizieren es mit $ provide.value ('$ cookieStore', cookieStoreSpy), während es sollte $ provide.value ('cookieStore', cookieStoreSpy); – gnom1gnom

+0

auch wenn es sich um einen Winkelservice handelt? Ich dachte, ich müsste es mit dem Dollar referenzieren. – uriDium

0

Hier ist ein Beispiel https://github.com/lucassus/angular-seed/blob/81d820d06e1d00d3bae34b456c0655baa79e51f2/test/unit/controllers/products/index_ctrl_spec.coffee#L3 ist es Coffeescript-Code mit Mokka + sinon.js aber die Idee ist die gleiche.

Grundsätzlich mit dem folgenden Code-Snippet ein Modul laden konnte und seine Dienste ersetzen:

beforeEach(module("myModule", function($provide) { 
    var stub = xxx; //... create a stub here 
    $provide.value("myService", stub); 
})); 

Später in der Spezifikation dieser Dienst stubbed injizieren könnte und tun Behauptungen:

it("does something magical", inject(function(myService) { 
    subject.foo(); 
    expect(myService).toHaveBeenCalledWith("bar"); 
})); 

Mehr Details und Tipps zum Mocking und Testen finden Sie in diesem ausgezeichneten Blog-Beitrag: http://www.yearofmoo.com/2013/09/advanced-testing-and-debugging-in-angularjs.html

0

Warum cookieStore mock, wenn Sie es direkt ohne mo verwenden können dification? Der unten stehende Code ist ein partieller Komponententest für einen Controller, der $ cookieStore zum Setzen und Abrufen von Cookies verwendet. Wenn Ihr Controller über eine Methode namens "setACookie" verfügt, die $ cookieStore.put ('cookieName', cookieValue) verwendet, sollte der Test in der Lage sein, den festgelegten Wert zu lesen.

describe('My controller', function() { 
    var $cookieStore; 
    describe('MySpecificController', function() { 

    beforeEach(inject(function(_$httpBackend_, $controller, _$cookieStore_) { 
     $cookieStore = _$cookieStore_; 
     // [...] unrelated to cookieStore 
    })); 

    it('should be able to reference cookies now', function() { 
     scope.setACookie(); 
     expect($cookieStore.get('myCookieName')).toBe('setToSomething'); 
    }); 

}); 
Verwandte Themen