I have a class that gets knockout messages using the method below:
public IEnumerable<Message> GetKnockoutMessages(Data data)
{
if(data.Messages != null)
{
return data.Messages.Where(m => m.UnderWritingRuleId != null);
}
else
{
return new List<Message>();
}
}
So far, i have a unit test that only partially covers the unit test which is below.
[TestMethod]
public void TestGetKnockoutMessages()
{
KnockoutUtility knockUtility = new KnockoutUtility();
IEnumerable<Message> messages = knockUtility.GetKnockoutMessages(MockData.Object);
Assert.IsNotNull(messages);
}
This covers everything but return data.Messages.Where(m => m.UnderWritingRuleId != null);
I was wondering how I would unit test this method to get 100% coverage.
Any help would be appreciated. Thanks
This unit test doesn't cover everything because you are not verifying all cases. You have to test two logics:
if/else logic
Where(m => m.UnderWritingRuleId != null) logic
Based on this assumption you have to create cases which proof following:
If data.Messages are null then you have to verify that method returns new instance of List<Message>() because you specified in code like that.
Next case will be to verify that method returns empty IEnumerable<Message> if data.Messages are empty (which means this condition data.Messages.Count() == 0).
Next case will be to verify that method returns exact messages which satisfied your condition: Where(m => m.UnderWritingRuleId != null). In other words only messages which have populated UnderWritingRuleId.
To achieve what I mentioned you have to create Data objects which satisfied this cases. I don't know what is MockData.Object but I hope that you included you arrangement there.
Each case should be in separate test method like in following:
[TestMethod]
public void TestGetKnockoutMessages_Case1()
{
// Arrange
// Action
// Assert
}
[TestMethod]
public void TestGetKnockoutMessages_Case2()
{
// Arrange
// Action
// Assert
}
[TestMethod]
public void TestGetKnockoutMessages_Case3()
{
// Arrange
// Action
// Assert
}
Arrange is place where you configuring your mock-ups. Action is place where you executing method which you want to test and Assert is place where you doing assertion.
Related
I want to test a method with no return, which only runs code if a passed in bool is set to true.
I'd like to test that when the bool is false, no code is called. I expect, this is maybe a case of refactoring to make my code more testable.
Code speaks a thousand words, so here's my method (constructor and dependencies left out for brevity):
...
public void Handle(Notification notification)
{
if (notification.IsRestarting)
{
var installedVersion = _versionService.GetValue("Version");
var packageVersion = "1.0.0";
if (installedVersion.IsNullOrWhiteSpace())
{
_service.Initialise();
}
_versionService.SetValue("Version", packageVersion);
}
}
...
I'm using Moq for mocking.
The _versionService actually sets the value in a SQL database table. This is a third-party service, though it is mockable.
So, if isRestarting is false, the method should do nothing. How do I test this, or make my code more testable?
You can check that your services were never called. Assuming that _versionService is a Mock<ISomeVersionService>. Some rough code -
[Test]
public void MyTest()
{
//call the method
Handle(new Notification { IsRestarting = false });
//verify nothing happened
_versionService.Verify(x => x.GetValue(It.IsAny<string>(), Times.Never))
//handle _service similarly
}
I'm trying to use FakeItEasy (version 4.9.1) to create unit tests for some legacy code. I've created two unit tests, one of which works just as expected, and one very similar which doesn't work despite lots of trial and error.
Here's an excerpt from the method that seems impossible to test:
public class PosMessageProcessor : IPosMessageProcessor
{
public void Execute()
{
PurchaseOrderRepository repo = new PurchaseOrderRepository();
...
try
{
m_PurchaseOrder = GetOrderForProcessing(repo);
...
And here's my test:
[TestMethod]
[TestCategory("POS")]
public void ExecuteTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
IPosMessageProcessor fakePosMessageProcessor = A.Fake<IPosMessageProcessor>();
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);
// Act
_posMessageProcessor.Execute();
// Assert
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}
The _posMessageProcessor variable is an instance of the PosMessageProcessor class. I want to catch the call to the GetOrderForProcessing() method (within the Execute() method) and make it return my hard-coded purchaseOrder object. But I get another return value (null) instead. Why?
The unit test that works tests the GetOrderForProcessing() method:
[TestMethod]
[TestCategory("POS")]
public void GetOrderForProcessingTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
IPurchaseOrderRepository fakePurchaseOrderRepository = A.Fake<IPurchaseOrderRepository>();
A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).Returns(purchaseOrder);
// Act
PurchaseOrder result = _posMessageProcessor.GetOrderForProcessing(fakePurchaseOrderRepository);
// Assert
A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).MustHaveHappened();
Assert.IsNotNull(result);
}
In this case, the call to GetPurchaseOrderByOrderTrackingNumber() returns my hard-coded object as expected. The two tests are virtually the same, except that the GetOrderForProcessing() method takes a parameter while Execute() does not.
ExecuteTest is failing because you configure a fake IPosMessageProcessor and then call Execute on a real PosMessageProcessor, _posMessageProcessor. _posMessageProcessor, being an actual PosMessageProcessor, executes its regular code path, calling the actual Execute, which will call the actual GetOrderForProcessing.
(Note that you can actually delete the fakePosMessageProcessor variable and all references to it from your test, and the behaviour will be the same.)
I do not recommend this kind of testing, but in order to fake GetOrderForProcessing and still test the actual Execute code, you would have to write a test like
public void NewExecuteTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
// Get a fake PosMessageProcessor that falls back to original behaviour for all calls.
IPosMessageProcessor fakePosMessageProcessor = A.Fake<PosMessageProcessor>(options => options.CallsBaseMethods());
// Now fake out the GetOrderForProcessing call so we can test Execute.
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);
// Act
fakePosMessageProcessor.Execute();
// Assert
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}
I want to write Unit test cases for following code
HomeController.cs
[HttpPost]
[ActionName("CreateDemo")]
public async Task<IHttpActionResult> CreateDemo([FromBody] MyRequest request)
{
if (request == null)
{
return BadRequest("request can not be null");
}
if (request.MyID == Guid.Empty)
{
return BadRequest("MyID must be provided");
}
}
I tried like following which is not correct way i guess so
[TestMethod]
public async Task NullCheck()
{
try
{
var controller = new HomeController();
var resposne = await controller.CreateDemo(null);
Assert.AreEqual(); // not sure what to put here
}
catch (HttpResponseException ex) //catch is not hit
{
Assert.IsTrue(
ex.Message.Contains("request can not be null"));
}
}
Each unit test shall test one requirement or concern. Your method implements two requirements:
1) If request is null, return BadRequestErrorMessageResult object with predefined error message.
2) If request's MyID property is empty GUID, return BadRequestErrorMessageResult object with another predefined error message.
This means we should have two unit tests:
[Test]
public async Task CreateDemo_returns_BadRequestErrorMessageResult_when_request_is_null()
{
// Arrange
var controller = new HomeController();
// Act
var response = await controller.CreateDemo(null);
// Assert
Assert.IsInstanceOf<BadRequestErrorMessageResult>(response);
Assert.AreEqual("request can not be null", response.Message);
}
[Test]
public async Task CreateDemo_returns_BadRequestErrorMessageResult_when_request_ID_is_empty_GUID()
{
// Arrange
var controller = new HomeController();
var request = new MyRequest(Guid.Empty);
// Act
var response = await controller.CreateDemo(request);
// Assert
Assert.IsInstanceOf<BadRequestErrorMessageResult>(response);
Assert.AreEqual("MyID must be provided", response.Message);
}
You can go even further and split each of these tests into two where one would test that return object is of the expected type and another that validates that returned object state is as expected (e.g. Message string is as expected). This way you would have a single assert per test.
Side notes:
You tagged this question with nunit tag so I provided the code which uses that framework. In your example though, you use [TestMethod] attribute which comes from Microsoft unit testing framework. If you want to use that framework you'd have to make some changes e.g. replace Assert.IsInstanceOf with Assert.IsInstanceOfType.
I assumed that GUID is passed to MyRequest via its constructor which assigns it to MyID.
I am not coming from web world but I found that BadRequest method has an overload which returns BadRequestErrorMessageResult if string is passed as its argument.
I'm using FakeItEasy to do some testing, but I have run into a problem.
When testing that the expected data is sent to a faked service, I would like to be able to see the error data as well.
Right now I only see that the call never happened.
Maybe I'm setting it up all wrong, but then I'd like some hints on how to correct it. :)
My case is:
A call to the same service twice, with different values.
I want separate tests to verify each call.
If any of the parameters, doesn't have the expected value, I would like to get an error message stating that. Similar to when you do an Assert.AreEqual().
Right now I only get "Call did not happen", which is totally understandable, because I realise that is what I'm testing. But I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I used this solution: http://thorarin.net/blog/post/2014/09/18/capturing-method-arguments-on-your-fakes-using-fakeiteasy.aspx
when I only had one call, but with two calls it doesn't work.
[TestFixture]
public class TestClass
{
[Test]
public void TestOne()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 2))).MustHaveHappened(Repeated.Exactly.Once);
}
[Test]
public void TestTwo()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 3))).MustHaveHappened(Repeated.Exactly.Once);
}
}
public class Foo
{
private readonly IBarservice _barservice;
public Foo(IBarservice barservice)
{
_barservice = barservice;
}
public void DoStuff(int someInt)
{
someInt++;
_barservice.DoOtherStuff(someInt);
// I should have increased someInt here again, but this is a bug that my tests catches
_barservice.DoOtherStuff(someInt);
}
}
public interface IBarservice
{
void DoOtherStuff(int someInt);
}
Markus, I had a comment that I've redacted, since I made an error.
You say you only get "Call did not happen" and
… I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I fear I don't understand what information you were hoping for, since when I run TestOne, I get
FakeItEasy.ExpectationException
Assertion failed for the following call:
FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(<x => (x == 2)>)
Expected to find it exactly once but found it #2 times among the calls:
1: FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(someInt: 2) repeated 2 times
...
This says that the call DoOtherStuff was made twice, with someInt passed in as the value 2 each time.
Scenario: I am learning how to unit test. Currently am working on tests for an mvc action method with nUnit and FakeItEasy. I have a test to verify that the method throws an exception if passed an id that doesn't exist. The action method calls a repository wrapper method for .Single(), which will throw an exception if nothing is found. This is good.
In my test, I do the following:
Create fake IRepository using FakeItEasy
Create test data
Configure .Single() wrapper method to get data from my test data
Problem: I am having issues testing this. The problem is that when passed an invalid id, an exception is thrown right in the configuration code for the fake repository, instead of in the action method itself. The reason why is obvious. The configuration code is ran before the action method gets executed, and the configuration code calls .Single() on the test data... which (intentionally of course) does not contain the invalid id. So it throws an exception right then and there, and never even makes it to the action method. What I am not sure about, is how to get around this. The exception needs to be thrown inside the action method. I don't know how to configure the return value in a way that avoids this conundrum.
Code:
Controller Code
public ViewResult Details(int id)
{
var dbPart = _repository
.GetSingleRecord<Part>(x => x.PartID == id);
var viewmodel = new DetailsViewModel()
{
PartID = dbPart.PartID
};
return View(viewmodel);
}
Test Code
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
// Create a fake PartID that exists
partID_that_exists = 1;
// Create a fake PartID that doesn't exist
partID_that_doesnt_exist = -100;
}
[Test]
public void an_exception_is_thrown_if_the_part_doesnt_exist()
{
// Arrange
FakeRepository.FakePartID = partID_that_doesnt_exist;
_fakeRepository = FakeRepository.Create();
_controller = new PartController(_fakeRepository);
// Act & Assert
Assert.Throws<InvalidOperationException>(() =>
_controller.Details(partID_that_doesnt_exist));
}
Fake Repository Code
public class FakeRepository
{
public static int? FakePartID { get; set; }
public static IBasicRepository Create()
{
// Create fake repository
var fakeRepository = A.Fake<IBasicRepository>();
// Create fake test data
var fakeParts = new List<Part>()
{
new Part()
{
PartID = 1, PartDesc = "Fake Part 1"
},
new Part()
{
PartID = 2, PartDesc = "Fake Part 2"
}
};
// Configure fake repository to return fake data
A.CallTo(() => fakeRepository.GetAllRecords<Part>())
.Returns(fakeParts);
if (FakePartID.HasValue)
{
/* BELOW CODE IS THE PROBLEM */
A.CallTo(fakeRepository)
.Where(call => call.Method.Name == "GetSingleRecord")
.WithReturnType<Part>()
.Returns(fakeParts.Single(x => x.PartID == FakePartID));
}
// Return the newly created & configured fakeRepository
return fakeRepository;
}
}
I figured it out. I needed to use ReturnsLazily() instead of Returns().
ReturnsLazily delays setting the method's return values until the method is actually called, instead of setting them when the method's configuration code is executed.
New, Working Code:
A.CallTo(fakeRepository)
.Where(call => call.Method.Name == "GetSingleRecord")
.WithReturnType<Part>()
.ReturnsLazily(() => fakeParts
.Single(x => x.PartID == FakePartID));