I have the following code:
class Clients
constructor : ->
@clients = []
createClient : (name)->
client = new Client name
@clients.push client
I am testing it with Jasmine BDD like this:
describe 'Test Constructor', ->
it 'should create a client with the name foo', ->
clients = new clients
clients.createClient 'Foo'
Client.should_have_been_called_with 'Foo'
it 'should add Foo to clients', ->
clients = new clients
clients.createClient 'Foo'
expect(clients.clients[0]).toEqual SomeStub
In my first test I want to check if the constructor is being called with the correct name. In my second I just want to confirm that whatever came out of new Client was added to the array.
I am using Jasmine BDD and it has a way to create spies/mocks/stubs but it seems it's not possible to test constructor. So I am looking into a way to test the constructor it would be nice if there is a way that I don't need an extra library but I am open to anything.
0, we can now mock Java constructors with Mockito. This allows us to return a mock from every object construction for testing purposes. Similar to mocking static method calls with Mockito, we can define the scope of when to return a mock from a Java constructor for a particular Java class.
if your constructor is calling a method of its own class, you can fake the call using this API: // Create a mock for class MyClass (Foo is the method called in the constructor) Mock mock = MockManager. Mock<MyClass>(Constructor. NotMocked); // Faking the call to Foo mock.
It uses field level annotations: @InjectMocks - Instantiates testing object instance and tries to inject fields annotated with @Mock or @Spy into private fields of testing object. @Mock - Creates mock instance of the field it annotates. @Spy - Creates spy for instance of annotated field.
It is possible to stub out constructors in Jasmine, the syntax is just a bit unexpected:
spy = spyOn(window, 'Clients');
In other words, you don't stub out the new
method, you stub out the class name itself in the context where it lives, in this case window
. You can then chain on a andReturn()
to return a fake object of your choosing, or a andCallThrough()
to call the real constructor.
See also: Spying on a constructor using Jasmine
I think the best plan here is to pull out the creation of the new Client
object to a separate method. This will allow you to test the Clients
class in isolation and use mock Client
objects.
I've whipped up some example code, but I haven't tested it with Jasmine. Hopefully you can get the gist of how it works:
class Clients
constructor: (@clientFactory) ->
@clients = []
createClient : (name)->
@clients.push @clientFactory.create name
clientFactory = (name) -> new Client name
describe 'Test Constructor', ->
it 'should create a client with the name foo', ->
mockClientFactory = (name) ->
clients = new Clients mockClientFactory
clients.createClient 'Foo'
mockClientFactory.should_have_been_called_with 'Foo'
it 'should add Foo to clients', ->
someStub = {}
mockClientFactory = (name) -> someStub
clients = new Clients mockClientFactory
clients.createClient 'Foo'
expect(clients.clients[0]).toEqual someStub
The basic plan is to now use a separate function (clientFactory
) to create new Client
objects. This factory is then mocked in the tests allowing you to control exactly what is returned, and inspect that it has been called correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With