I am using sinon mock as follows
var sandbox = sinon.sandbox.create();
var mockPictureUrl = "http://test.com/test.gif";
var opts = { getUserPictureURL: function () {} };
var mock = sandbox.mock(opts);
mock.expects("getUserPictureURL").once().returns(mockPictureUrl); expect(AuthController.getUserProfilePictureUrl()).to.equal(mockPictureUrl);
mock.verify();
mock.restore();
If we call sandbox.restore() do we have to call mock.restore()?
Is that the correct way to use sinon mocks?
You are right, with sandbox.restore() you restore all spied, mocked and stubbed objects inside the sandbox, what is very convenient if you have many in your test, since there is no need of restoring the faked objects individually.
You can read more about the sandbox utility in Sinon.JS webpage.
If you are mocking only one object, you could decide to not create a sandbox, and instead mock and restore the object directly.
Related
I am trying to test a function in one of my component which consists following two lines:
this.rzp1 = new Razorpay(orderDetails);
this.rzp1.open();
I am trying to understand how to mock Razorpay in my test cases for this function.
This is how I am declaring Razorpay in my component:
export declare var Razorpay: any;
I have already tried various methods like:
var stub = sinon.createStubInstance(MyConstructor)
Any leads will be helpful.
Why not use jasmine's built in spy facility instead of relying on another library (sinon)?
In your before each block, you can do something like this:
beforeEach(() => {
jasmine.spyOnAllFunctions(Razorypay.prototype);
Razorypay.prototype.open.and.returnValue('foo');
});
You can find more information about spyOnAllFuntions in the documentation.
So I've build a WebAPI from scratch, including some best practices that I've found online such as Dependency Injection and Domain<->DTO mapping using auto mapper etc.
My API Controllers now look similar to this
public MyController(IMapper mapper)
{
}
and AutoMapper Registry:
public AutoMapperRegistry()
{
var profiles = from t in typeof(AutoMapperRegistry).Assembly.GetTypes()
where typeof(Profile).IsAssignableFrom(t)
select (Profile)Activator.CreateInstance(t);
var config = new MapperConfiguration(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
});
For<MapperConfiguration>().Use(config);
For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));
}
I'm also building a few test cases, implementing MOQ, and this is where i feel a little unsure. whenever calling my controllers, I need to pass in an IMapper like this:
var mockMapper = new Mock<IMapper>();
var controller = new MyController(mockMapper.Object);
But then, how do i configure the IMapper to have the correct mappings? It feels redundant to recreate the same logic I've already created before to configure the Mapper. so I am wondering what is the recommended approach to do this?
That's pretty simple: if you mock IMapper and imagine it as a fully abstract concept of mapping data from one object to another, then you have to treat is an abstraction and not imply there's a real automapper behind it.
First you should not register any existing profile at all, you should instead setup IMapper.Map method to return specific object when given another object.
So for each profile used for specific method you have to do a setup, looking approximately like this:
var mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map<DestinationClass>(It.IsAny<SourceClass>()))
.Returns((SourceClass source) =>
{
// abstract mapping function code here, return instance of DestinationClass
});
In this case, your test knows nothing about actual IMapper implementation - it just uses it methods to get the data you expect from actual IMapper implementation to receive.
This might me another solution
//auto mapper configuration
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfile()); //your automapperprofile
});
var mapper = mockMapper.CreateMapper();
And then call then controller like so
var controller = new YourController(imapper:mapper,..otherobjects..);
This way it will serve the purpose or else if you create mock object for IMapper then it will return what you ask it to return.
If I use sinon with typescript then how do I cast the sinon mock to an instance of my object?
For instance a SinonMock would be returned but my controller under test may require a specific service passed in to its constructor.
var myServiceMock: MyStuff.MyService = <MyStuff.MyService (sinon.mock(MyStuff.MyService));
controllerUnderTest = new MyStuff.MyController(myServiceMock, $log);
Can sinon be used with Typescript?
Sinon can create a stub based on a constructor quite easily if, instead of mock, you use the createStubInstance method.
An example using mocha, chai, sinon and sinon-chai, could look like this:
import * as sinon from 'sinon';
import * as chai from 'chai';
// ... imports for the classes under test
const expect = chai.expect;
const sinonChai = require("sinon-chai");
chai.use(sinonChai);
describe('MyController', () => {
it('uses MyService', () => {
let myService = sinon.createStubInstance(MyStuff.MyService),
controller = new MyStuff.MyController(myService as any, ...);
// ... perform an action on the controller
// that calls myService.aMethodWeAreInterestedIn
// verify if the method you're interested in has been called if you want to
expect(myService.aMethodWeAreInterestedIn).to.have.been.called;
});
});
I've published an article, which you might find useful if you'd like to learn more about the different test doubles and how to use them with Sinon.js.
Hope this helps!
Jan
You may need to use an <any> type assertion to make the type wide before you narrow it to your specific type:
var myServiceMock: MyStuff.MyService =
<MyStuff.MyService> <any> (sinon.mock(MyStuff.MyService));
Just to clarify one behaviour of sinon - although you pass in MyStuff.MyService, whatever you pass to the mock method is only used to provide better error messages.
If you want the mock to have methods and properties, you need to add them.
If you want automatically created fakes, you can grab the FakeFactory from tsUnit, which creates a fake version with some default values that you can opt to override - in JavaScript this is pretty easy stuff (plus by not using too much mock functionality, you can ensure you are testing behaviour rather than implementation).
Example use of FakeFactory:
var target = tsUnit.FakeFactory.getFake<RealClass>(RealClass);
var result = target.run();
this.areIdentical(undefined, result);
In Typescript this can be achieved by using sinon.createStubInstance and SinonStubbedInstance class.
Example:
let documentRepository: SinonStubbedInstance<DocumentRepository>;
documentRepository = sinon.createStubInstance(DocumentRepository);
Now you have a full intellisense for working with all stubbed methods of this class.
Example Arrange:
documentRepository.delete.resolves({deletedCount: 1});
documentRepository.update.throws(error);
Example Assert:
sinon.assert.calledOnce(documentRepository.update);
There is only one place where you would need to perform type casting and that is the initiallization of the class you want to unit test.
Example:
documentsController =
new DocumentsController(
userContext,
documentRepository as unknown as DocumentRepository);
Hope this will help.
More on this article.
Use ts-sinon.
It lets you:
stub objects
stub interfaces
Sorry if this comes across as a stupid question im just not sure how to get started writing some unit tests.
I have a solution containing an api and a unit test project. The api has a repository/interface used for data access using ninject.
My question is how is my best way to unit test my api controllers. I have read a little about Moq but not sure if I need to use it as I want to test against my database.
I have read that I need to use a [TestInitialize] attribute
[TestInitialize]
public void MyTestInitialize()
{
var kernel = NinjectWebCommon.CreatePublicKernel();
kernel.Bind<BusinessController>().ToSelf();
}
My problem is my test project cant resolve CreatePublicKernel
Checking the NinjectWebCommon class in the api there is no function called CreatePublicKernel.
What am I missing here?
Ninject (or other DI library) is used only to provide dependencies into your controller's constructor. E.g. if you need BusinessController which requires two repositories, then controller should have constructor which expects these dependencies:
public BusinessController(IUserRepository userRepository,
IOrderRepository orderRepository)
{
_userRepository = userRepository;
_orderRepository = orderRepository;
}
If you want to write unit tests for your controller, you should provide mocked implementations of these repositories. Use Moq or other framework for creating mocks:
var userRepositoryMock = new Mock<IUserRepository>();
var orderRepositoryMock = new Mock<IOrderRepository>();
// setup mocks here
var controller = new BusinessController(userRepositoryMock.Object,
orderRepositoryMock.Object);
If you are writing integration tests for your controller, you should provide real implementations of these repositories, which use some real database.
var userRepository = new NHibernateUserRepository();
var orderRepository = new NHibernateOrderRepository();
// prepare some data in database here
var controller = new BusinessController(userRepository, orderRepository);
You can move controller instantiation into some method which is executed before each test (SetUp or TestInitialize method) in order to remove code duplication from your tests.
UPDATE: You also can use Ninject for integration testing. Just create Ninject module which will be used both by your real application and integration tests:
public class FooModule : NinjectModule
{
public override void Load()
{
Bind<IUserRepository>().To<NHibernateUserRepository>();
Bind<IOrderRepository>().To<NHibernateOrderRepository>();
Bind<BusinessController>().ToSelf();
}
}
Then use this module both to create kernel in NinjectWebCommon.CreateKernel method and kernel in your tests:
var kernel = new StandardKernel(new FooModule());
var controller = kernel.Get<ValuesController>();
Just wondering it is possible to setup a mock inside a mock ? I mean a mock than get configured to return another mock which has a specific setup.
I am using Moq.
Thanks!
Looking at the moq site (and using what I know of RhinoMock) I suspect you could do something like:
var innerMock = new Mock<IInnerClass>();
// TODO - Setup innerMock expectations
var outerMock = new Mock<IOuterClass>();
outerMock.Setup(i => i.GetInner()).Returns(innerMock.Object);