using jasmine / spyOn to mock properties on an object - unit-testing

Is it possible to mock some properties on an object using Jasmine .spyOn()?
Basically, imagine I have a Page object that has title, deliveryTime and status that I want to mock it such that I just have to set the title property title = 'test' ; the other two properties can have any value (of their correct type) as are not relevant for my testing scenario.
Some test fake code would be:
spyOnProperty(page, "title").and.returnValue(test);
This would be equivalent to C# / Moq as:
mock.Setup(foo => foo.Name).Returns("bar");

Related

Error when trying to mock CakePHP 3 component

I am trying to mock a CakePHP 3 component which checks if the user is allowed to view the page or not.
I tried this:
$authComponent = $this->getMockBuilder(App\Controller\Component\AuthorizationComponent::class)
->getMock();
$authComponent
->method('isAuthorized')
->willReturn($this->returnValue(true));
However, when running the test, it says:
Trying to configure method "isAuthorized" which cannot be configured because it does not exist, has not been specified, is final, or is static
Most probably I wrongly created the mock. Can anyone tell me how to do it correctly?
Specify mocked methods with setMethods() before getMock():
$authComponent = $this
->getMockBuilder(App\Controller\Component\AuthorizationComponent::class)
->setMethods(['isAuthorized'])
->getMock();

Unit testing with Moq, Prism 6, and Event Aggregation

I want to unit test a module by throwing messages at it via Event Aggregation to make sure it responds appropriately, either by setting properties appropriately, or by publishing other messages as a result. I am using Prism 6.
In my project, the infrastructure project has:
public class ImportantMessage : PubSubEvent<string>
{
}
ModuleA publishes a message like this:
eventAggregator.GetEvent<ImportantMessage>().Publish(importantString);
ModuleB receives the message like this:
eventAggregator.GetEvent<ImportantMessage>().Subscribe(HandleImportantMessage);
Here is HandleImportantMessage:
public void HandleImportantMessage(string importantString)
{
. . .
}
The ModuleB constructor is called as follows:
ModuleB(IEventAggregator EventAggregator)
This constructor is called by the Prism framework. For unit testing, I need to create an instance of ModuleB, and pass an IEventAggregator, probably a fake one created by Moq. And I want to do this in such a way that the message I publish carries importantString with it.
If I Google the phrase “unit tests with moq and event aggregation,” there are
several references, but I didn’t see how to use any of these approaches to pass “importantString” from ModuleA To ModuleB. The sample code for Prism 5 creates a fake event aggregator, but without using Moq. I don't understand how it works, and don't see how to pass a string with it.
My test code starts off something like this:
var moqEventAggregator = new Mock(IEventAggregator);
var moqImportantMessage = new Mock<ImportantMessage>();
moqEventAggregator.Setup(x => x.GetEvent<ImportantMessage>());
Some of the references I have seen apply something like .Returns(eventBeingListenedTo.Object);
to moqEventAggregator after Setup is applied.
I obviously need to apply .Setup(something) to moqImportantMessage in order to pass importantString, but I don't see exactly what yet.
What am I missing? How do I pass a string with the fake published message?
Basically you need to mock 2 things here:
The event aggregator
The event itself
Given you have the mock of the event you need to do as you said:
moqEventAggregator.Setup(x => x.GetEvent<ImportantMessage>()).Returns(moqImportantMessage);
Mocking the event itself should be like so:
Action<string> action;
moqImportantMessage.Setup(_ => _.Subscribe(It.IsAny<Action<string>>>()))
.Callback(_action =>
{
action = _action;
});
And then you can raise the subscription like so:
action("some string");

How do I use Sinon with Typescript?

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

How to mock g.message while writing unit test for grails controller

I am using grails version 1.3.7. In my application in controller, I am making use of messages.properties and fetching the value of the property as
g.message(code:messageKey, args:msgParamsArr)
But when I started writing unit tests for the action in the controller, it gave me errors.
Please can you help me out to understand how to mock g.message exactly so that the existing code will fetch the message properties from messages.properties only.
You can mock it with:
controller.metaClass.message = { message ->
message.code
}
You can include message.args too if you want to just validate the arguments with .contains().
This works like a champ in Grails 2.4.5:
controller.metaClass.message = { Map attrs -> attrs.toString() }

Using Moq callbacks correctly according to AAA

I've created a unit test that tests interactions on my ViewModel class in a Silverlight application. To be able to do this test, I'm mocking the service interface, injected to the ViewModel. I'm using Moq framework to do the mocking.
to be able to verify bounded object in the ViewModel is converted properly, I've used a callback:
[Test]
public void SaveProposal_Will_Map_Proposal_To_WebService_Parameter()
{
var vm = CreateNewCampaignViewModel();
var proposal = CreateNewProposal(1, "New Proposal");
Services.Setup(x => x.SaveProposalAsync(It.IsAny<saveProposalParam>())).Callback((saveProposalParam p) =>
{
Assert.That(p.plainProposal, Is.Not.Null);
Assert.That(p.plainProposal.POrderItem.orderItemId, Is.EqualTo(1));
Assert.That(p.plainProposal.POrderItem.orderName, Is.EqualTo("New Proposal"));
});
proposal.State = ObjectStates.Added;
vm.CurrentProposal = proposal;
vm.Save();
}
It is working fine, but if you've noticed, using this mechanism the Assert and Act part of the unit test have switched their parts (Assert comes before Acting). Is there a better way to do this, while preserving correct AAA order?
I'm not sure that you've changed the semantics of the AAA order. Consider the execution of the test. Your mocked interface will not be called until the Action invokes it. Therefore, during execution, your program still follows the Arrange, Act, and Assert flow.
The alternative would be to use Data Injection and create an interface between your CampaignViewModel and the web service that it uses. You can then create a class in your UnitTests that saves your parameter information and Assert on that class member/property rather than use Moq to create a proxy on the fly.
Moq should not be used to simulate storage or assignment. Rather, use Moq to provide dummy mechanisms and values to allow your Unit Tests to execute. If Asserting storage is a requirement, then take the time to create a class that will hold on to your values.