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);
Related
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.
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.
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
Help me understand how to mock a service method inside a controller for unit testing in grails using JUnit
I was trying to write a unit test case for my controller "add".
void testAdd_UT_03(){
......declaring and assigning prerequisites
controller.add() // This is the controller i want to unit test
.... asserting
}
//Controller
def add{
def a =someService.method()
}
Inside controller, some service methods are getting called which in turn is using HQL statements. Since i could not find a way to deal with HQL statements in unit testing, i want to mock the service method itself. ( i want the service method to return the predefined output).
Could someone please explain how to achieve this?
Could you also explain when to use mockController? what we really achieve by mocking something? ( i dint get the real picture as i am entirely new to this)
Thanks in advance,
BK
you can add the following code in the setUp method of your test to mock the service method and when you call the method "add" method on your controller it will call the mocked service method.
def predifinedOutput
void setUp(){
def mockControl = mockFor(YourService)
//params are the parameters passed to the service method
mockControl.demand.yourServiceMethod(0..10) { params->
predifnedOutput = "predifinedOutput"
return "predefined output"
}
controller.yourService = mockControl.createMock()
}
I have a module that contains resources for a project, and the code looks like this:
editor_services.js
var editorServices = angular.module('editorServices', ['ngResource']);
editorServices.factory('Project', ['$resource', '$http',function($resource, $http){
//...etc
now I would like to write tests for a controller that expects a project resource as an argument. How can I get an instance of the project resource that is created by this factory out of the editorServices variable?
Here is a working example how one would test Resources (or http) in angular
http://plnkr.co/edit/kK5fDFIVpyZTInH1c6Vh?p=preview
The basic setup is:
load angular-mocks.js in your test. This replaces the $httpBackend with mock version. See: http://docs.angularjs.org/api/ngMock.$httpBackend
In your test call $httpBackend.expect() to create expectation to be mocked out.
When you want to simulate server response call $httpBackend.flush()
There is a caveat that normal .toEqual() from jasmine dose not work with $resource so you have to create custom matcher like so:
beforeEach(function() {
this.addMatchers({
// we need to use toEqualData because the Resource hase extra properties
// which make simple .toEqual not work.
toEqualData: function(expect) {
return angular.equals(expect, this.actual);
}
});
});