Spy on a field assignment using Jasmine - unit-testing

How could I spy on a field assignment using Jasmine?
E.g. I have the object under test:
const testObj = {
testObjField: null,
testObjFunc: function() { this.testObjField = "foo"; }
}
Now I want to assert that the testObj.testObjFunc will assign the "foo" to the testObj.testObjField. How should I proceed?
Here is what I tried:
//arrange
const testObj = {
testObjField: null,
testObjFunc: function () {
this.testObjField = 'foo';
}
};
const testObjTestObjFieldSpy = spyOnProperty(testObj, 'testObjField', 'set');
//act
testObj.testObjFunc();
//assert
expect(testObjTestObjFieldSpy).toHaveBeenCalledWith('foo');
But I am getting the error:
Error: : Property testObjField does not have access type set

You can't spy on fields, only on methods.
I would do this:
//arrange
let testObj = {
testObjField: null,
testObjFunc: function () {
this.testObjField = 'foo';
}
};
// !! Get a copy of the original
const originalTestObj = { ...testObj };
//act
testObj.testObjFunc();
//assert
expect(testObj.testObjField).toBe('foo');
// !! Reset testObj to what it was if that is required
testObj = { ...originalTestObj };

Related

Testing Dart class that runs code on Isolate

I have a Dart class that performs computations on Isolate. Here is my code:
class Mapper {
SendPort _isolateSendPort;
Isolate _isolate;
Mapper() {
_asyncInit();
}
void _asyncInit() async {
final receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_mappingFunction,
receivePort.sendPort,
);
_isolateSendPort = await receivePort.first;
}
static void _mappingFunction(SendPort callerSendPort) {
final newIsolateReceivePort = ReceivePort();
callerSendPort.send(newIsolateReceivePort.sendPort);
newIsolateReceivePort.listen((dynamic message) {
final crossIsolatesMessage =
message as CrossIsolatesMessage<Input>;
// some computations...
crossIsolatesMessage.sender.send(output);
});
}
Future<Output> map(Input input) async {
final port = ReceivePort();
_isolateSendPort.send(CrossIsolatesMessage<Input>(
sender: port.sendPort,
message: input,
));
return port.map((event) => event as Output).first;
}
void dispose() {
_isolate?.kill(priority: Isolate.immediate);
_isolate = null;
}
}
class CrossIsolatesMessage<T> {
final SendPort sender;
final T message;
CrossIsolatesMessage({
#required this.sender,
this.message,
});
}
This code works well when I run Flutter app. But unit test for public method Future<Output> map(Input input) throws an error NoSuchMethodError which meens _isolateSendPort is null.
Here is the unit test code:
test('Mapper map', () {
final sut = Mapper();
final inputDummy = Input('123');
final resultFuture = sut.map(inputDummy);
final expectedResult = Output('321');
expectLater(resultFuture, completion(expectedResult));
});
Here is an error:
NoSuchMethodError: The method 'send' was called on null.
Receiver: null
Tried calling: send(Instance of 'CrossIsolatesMessage<Input>')
dart:core Object.noSuchMethod
Why this error occurs in tests? And what is the right way to write tests for this class?
Problem solved.
Create of _isolate and _isolateSendPort is an async operation. Thats why _isolateSendPort was null on tests. Call method _asyncInit() from Mapper constructor is wrong way to create an isolate.
Here is working solution with lazy isolate initialization:
class Mapper {
SendPort _isolateSendPort;
Isolate _isolate;
void _initIsolate() async {
final receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_mappingFunction,
receivePort.sendPort,
);
_isolateSendPort = await receivePort.first;
}
...
Future<Output> map(Input input) async {
final port = ReceivePort();
if (_isolateSendPort == null) {
await _initIsolate();
}
_isolateSendPort.send(CrossIsolatesMessage<Input>(
sender: port.sendPort,
message: input,
));
return port.map((event) => event as Output).first;
}
...
}

In in moq unit test how to fix "Object reference not set to an instance of an object"

Okay I am trying to create a test that checks that my badge method actually added a badge to PlayersBadge. It works but I don't know how to test properly. The main issue is my understanding of moq.
This is my method it takes in a PlayerID, BadgeID, and GameID.
public bool Badge(int pID, int bID, int gID = 0)
{
var list = EliminationDbContext.PlayerBadges.Where(x => x.Badge.BadgeID.Equals(bID) && x.Player.PlayerID.Equals(pID));
if (list.Any() != true)
{
PlayerBadge b = new PlayerBadge { PlayerID = pID, BadgeID = bID, DateEarned = DateTime.Today, GameID = gID };
_RepoManager.PlayerBadges.Add(b);
_RepoManager.SaveDb();
return true;
}
return false;
}
Currently I am getting this error "Object reference not set to an instance of an object" I think it's because I'm not setting up a mock of PlayerBadge correctly but I'm not sure how to fix this
[Test]
public void testing()
{ //Arrange
var mock = new Mock<IRepoManager>();
var mockRequest = new Mock<PlayerBadge>();
var dManager = new TestMoq(mock.Object);
//set mockRequest to playerBadge
mockRequest.Setup(x => x.Badge.PlayerBadges.Add(badge));
//Act
//Object reference not set to an instance of an object on this line
dManager._RepoManager.PlayerBadges.Add(mockRequest.Object);
dManager._RepoManager.Badges.Badge(1, 2, 0);
Assert.That(dManager._RepoManager.PlayerBadges.GetPlayerBadges().Count() >= 1);
}

Moq returns NotSupportedException in SearchAsync<T> test

I am getting a NotSupportedException error message on my Unit Test using Moq.
I have the following test which mocks the result.
public class Person
{
public string Id { get; set; }
}
[Test]
public void List_Should_List_All_People()
{
//Arrange
const long total = 3;
var list = new List<Person>();
var queryResponse = new Mock<Task<ISearchResponse<Person>>>();
queryResponse.Setup(x => x.Result.Total).Returns(total);
for (var i = 0; i < total; i++)
{
list.Add(new Person { Id = Guid.NewGuid().ToString() });
}
queryResponse.Setup(x => x.Result.Documents).Returns(list);
Thread.Sleep(2000);
_elasticClient.Setup(x => x.SearchAsync(It.IsAny<Func<SearchDescriptor<Person>, ISearchRequest>>())).Returns(queryResponse.Object);
// Act
var response = _repository.List<Person>();
//Assert
response.Count().Should().Be(3);
}
queryResponse.Setup(x => x.Result.Total).Returns(total); <-- an exception is thrown
Invalid setup on a non-virtual (overridable in VB) member: mock => mock.Result
It works synchronously without any problems.
Any suggestions how to get around this exception?
How can I set it as virtual?
You mock the Task<ISearchResponse<Person>> but not the ISearchResponse<Person> task result.
Here's an example of mocking a task result; you don't have all of the types that you're working with in your example so I've simplified this a little
async void Main()
{
var elasticClient = new Mock<IElasticClient>();
//Arrange
const long total = 3;
var list = new List<Person>();
for (var i = 0; i < total; i++)
{
list.Add(new Person { Id = Guid.NewGuid().ToString() });
}
var searchResponse = new Mock<ISearchResponse<Person>>();
searchResponse.Setup(x => x.Total).Returns(total);
searchResponse.Setup(x => x.Documents).Returns(list);
_elasticClient.Setup(x => x.SearchAsync(It.IsAny<Func<SearchDescriptor<Person>, ISearchRequest>>()))
.ReturnsAsync(searchResponse.Object);
// Act
var response = await elasticClient.Object.SearchAsync<Person>(s => s.MatchAll());
//Assert
// outputs 3
Console.WriteLine(response.Documents.Count());
}
public class Person
{
public string Id { get; set; }
}

SPEmulator and Microsoft Fakes

Hi I'm trying to run a simple test replacing Features.Count on every SPSite, but I can't. Can you help me?
I have this code:
[TestMethod]
public void AllInstances()
{
using (var context = new SPEmulationContext(IsolationLevel.Fake))
{
ShimSPSite.AllInstances.FeaturesGet = (item) =>
{
return new ShimSPFeatureCollection()
{
CountGet = () => 1
}.Instance;
};
var tSite = new SPSite("http://fakesite");
Assert.AreEqual(1, tSite.Features.Count);
}
}
but it fails with this exception:
Microsoft.QualityTools.Testing.Fakes.Shims.ShimNotImplementedException: Exception of type 'Microsoft.QualityTools.Testing.Fakes.Shims.ShimNotImplementedException' was thrown.
This one which is similar works fine
[TestMethod]
public void Shim()
{
using (var context = new SPEmulationContext(IsolationLevel.Fake))
{
var tSite = new ShimSPSite()
{
FeaturesGet = () =>
{
return new ShimSPFeatureCollection()
{
CountGet = () => 1
}.Instance;
}
}.Instance;
Assert.AreEqual(1, tSite.Features.Count);
}
}
Can you tell me what I'm doing wrong?
Thanks

Unit testing generic htmlHelper methods with nunit

I'm new to nUnit and I've been tasked with creating unit tests for some htmlhelper extension methods.
How should I go about creating a unit test for the following method?
public static MvcHtmlString EnumDropDownListForOrderBy<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, bool orderById, string firstElement = null, object htmlAttributes = null)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = values.Select(value => new SelectListItem()
{
Text = value.GetAttributeFrom<DescriptionAttribute>(value.ToString()).Description,
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
IEnumerable<SelectListItem> itemsFiltered = items.Where(e => !string.IsNullOrEmpty(e.Text)).AsEnumerable();
itemsFiltered = itemsFiltered.OrderBy(e => (orderById ? e.Text : e.Value));
return htmlHelper.DropDownListFor(
expression,
itemsFiltered,
firstElement,
htmlAttributes
);
}
Any help would be appreciated
Below is how you write a Unit Test for this. Note that since you have not specified that you use a Mock object framework I'm going to the poor man technique, which is the hand written stubs and mocks. There is also another helper method if you are using Moq.
It is important to note that, in order to simplify the code execution I have made couple of changes to your extension method, so the test would not fail unexpectedly. Checking for any unexpected behaver is a good defensive programming practice anyway.
Back to the tests.
SUT (System Under Test)
This is how the SUT (System Under Test) looks like and supporting types looks like. (Please feel free to modify to your need accordingly)
public static class MyHtmlHelper
{
public static MvcHtmlString EnumDropDownListForOrderBy<TModel, TEnum>
(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression,
bool orderById, string firstElement = null, object htmlAttributes = null,
Func<ModelMetadata> fromLambFunc = null)
{
ModelMetadata metadata =
ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items =
values.Select(value => new SelectListItem()
{
Text = GetText(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
IEnumerable<SelectListItem> itemsFiltered =
items.Where(e => !string.IsNullOrEmpty(e.Text)).AsEnumerable();
itemsFiltered = itemsFiltered.OrderBy(e => (orderById ? e.Text : e.Value));
return htmlHelper.DropDownListFor
(expression, itemsFiltered, firstElement, htmlAttributes);
}
private static Type GetNonNullableModelType(ModelMetadata metadata) {
return typeof (SomeEnum);
}
private static string GetText<TEnum>(TEnum value) {
return value.GetAttributeFrom<DescriptionAttribute>(value.ToString()) != null
? value.GetAttributeFrom<DescriptionAttribute>(value.ToString()).Description
: string.Empty;
}
}
public static class ExtensionMethodsAttr
{
public static T GetAttributeFrom<T>(this object instance, string propertyName)
where T : Attribute
{
var attrType = typeof(T);
var property = instance.GetType().GetProperty(propertyName);
return property != null ?
(T)property.GetCustomAttributes(attrType, false).First() : default(T) ;
}
}
public enum SomeEnum { A,}
Unit Tests
[TestFixture]
public class HtmlHelperTests
{
[Test]
public void EnumDropDownListForOrderBy_InvokeDropDownListFor_ReturnsExpectedSelectItemResult()
{
//Arrange
var expected = "<select id=\"Foo\" name=\"Foo\"></select>";
var fakeHtmlHelper = CreateHtmlHelperStaticStubs
(new ViewDataDictionary(new FakeViewModel() {Foo = SomeEnum.A}));
//var fakeHtmlHelper = CreateHtmlHelperUsingMoq
(new ViewDataDictionary(new FakeViewModel(){Foo = SomeEnum.A}));
//Act
var result = fakeHtmlHelper.EnumDropDownListForOrderBy
(model => model.Foo, It.IsAny<bool>(), null, null, null);
//Assert
Assert.AreEqual(expected, result.ToString());
}
private static HtmlHelper<FakeViewModel>
CreateHtmlHelperStaticStubs(ViewDataDictionary viewData)
{
var stubControllerContext = new ControllerContext(new FakeHttpContext(), new RouteData(), new FakeController());
var stubViewContext = new ViewContext(stubControllerContext, new FakeView(),
new ViewDataDictionary(new FakeViewModel() { Foo = SomeEnum.A }),
new TempDataDictionary(), new TextMessageWriter());
var fakeViewDataContainer = new FakeViewDataContainer();
fakeViewDataContainer.ViewData = viewData;
return new HtmlHelper<FakeViewModel>(stubViewContext, fakeViewDataContainer);
}
//Moq version
private static HtmlHelper<FakeViewModel>
CreateHtmlHelperUsingMoq(ViewDataDictionary viewData)
{
var stubControllerContext = new Mock<ControllerContext>();
stubControllerContext.Setup(x => x.HttpContext).Returns(new Mock<HttpContextBase>().Object);
stubControllerContext.Setup(x => x.RouteData).Returns(new RouteData());
stubControllerContext.Setup(x => x.Controller).Returns(new Mock<ControllerBase>().Object); ;
var stubViewContext = new Mock<ViewContext>();
stubViewContext.Setup(x => x.View).Returns(new Mock<IView>().Object);
stubViewContext.Setup(x => x.ViewData).Returns(viewData);
stubViewContext.Setup(x => x.TempData).Returns(new TempDataDictionary());
var mockViewDataContainer = new Mock<IViewDataContainer>();
mockViewDataContainer.Setup(v => v.ViewData).Returns(viewData);
return new HtmlHelper<FakeViewModel>(stubViewContext.Object, mockViewDataContainer.Object);
}
}
class FakeHttpContext : HttpContextBase
{
private Dictionary<object, object> _items = new Dictionary<object, object>();
public override IDictionary Items { get { return _items; } }
}
class FakeViewDataContainer : IViewDataContainer
{
private ViewDataDictionary _viewData = new ViewDataDictionary();
public ViewDataDictionary ViewData { get { return _viewData; } set { _viewData = value; } }
}
class FakeController : Controller { }
class FakeView : IView
{
public void Render(ViewContext viewContext, System.IO.TextWriter writer)
{
throw new NotImplementedException();
}
}
public class FakeViewModel {
public SomeEnum Foo { get; set; }
}