unit testing structuremap provides an implementation - c#

how can I write a unit test to test that asking for an interface does provide an implementation? I'm using NUnit together with StructureMap
Maybe something like this based on examples in the code? The problem I have is that I don't know how to setup the test.
Code snippet
[Test]
public void TestCustomerRegistration()
{
var res = ObjectFactory.GetInstance<ICustomer>();
Assert.IsNotNull(res, "Cannot get an Customer");
}
This is already present in the code
Not sure if I have to use a similar thing for my ICustomer test? Not sure what this is.
[TestFixtureSetUp]
public void SetUp()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<InfrastructureRegistry>();
x.AddRegistry<RepositoryRegistry>();
});
var container = ObjectFactory.Container;
IDependencyResolver resolver = new SmDependencyResolver(container);
ObjectFactory.Configure(x =>
{
x.For<IDependencyResolver>().Use(resolver);
});
}
Take the folloing MVC controller
I need to write a test that StructureMap provides 'Customer' when the _customer.GetById(id) is called. Hope this helps
private ICustomer _customer;
public MyController(ICustomer customer)
{
_customer = customer;
}
public ActionResult GetCustomer(int id)
{
var result = _customer.GetById(id); // I need to test that _customer works
}
Thanks,

If you are writing useless tests for checking some configuration of StructureMap (which is used for unit-tests, not for real running application), then it's easy to do! Use Assert.IsInstanceOf<T> to check exact type of returned object. It should be type which you are expecting StructureMap configured to return for customer interface:
[Test]
public void TestCustomerRegistration()
{
var customer = ObjectFactory.GetInstance<ICustomer>();
Assert.IsNotNull(customer, "Cannot get an Customer");
Assert.IsInstanceOf<SpecificCustomerType>(customer, "Wrong customer type");
}
UPDATE you should test controller in isolation from other objects (otherwise you will not know source of failures) and your controller test should look like (Moq sample)
[Test]
public void ShouldReturnExistingCustomer()
{
// Arrange
int id = 42; // or random numer
var dto = // data which ICustomer should return
Mock<ICustomer> customerMock = new Mock<ICustomer>();
customerMock.Setup(c => c.GetById(id)).Returns(dto)
var controller = new MyController(customer.Object);
// Act
var result = controller.GetCustomer(id);
// Assert
customerMock.VerifyAll();
Assert.IsNotNull(result); // etc
}
This is a controller test and it verifies that controller works (and calls customer to get data). If you want to verify _customer works, then you should write customer tests.

Related

Unti Test: Mock a method result

public void Pay()
{
// some insert db code
// ...
// Call Bank api
BankApi api = new BankApi();
int result = api.pay();
if(result == 1)
{
//...
}
else
{
//...
}
}
I dont want to call api in unit test. How to mock the pay method without modify inner code (such as the line new BankApi() code)?
Its possible to mock your BankApi class without changing any of your legacy code, you just need a unit testing framework that allows you to mock concrete classes.
for example a test for your method with Typemock :
[TestMethod]
public void ExampleTest()
{
//fakes the next BankApi instace
var handler = Isolate.Fake.NextInstance<BankApi>();
//change the pay method behavior
Isolate.WhenCalled(() => handler.pay()).WillReturn(1);
new ClassUnderTest().Pay();
}
First, as stated, you should create an Interface.
public interface IBankApi
{
int pay();
}
Then, what you can do is mock this interface like this (I'm using Moq "Mock you" here, you will need to add the NuGet package "Moq" as reference to your application, and you could use other mocking libraries of course)
apiMock = new Mock<IBankApi>();
just after that you will tell what this call should return (that would be actual mocking)
apiMock.Setup(x => x.pay()).Returns(1); //
Then, this api "pseudo object", can be used by using apiMock.Object
Now , this information I just gave you doesn't directly solve your problem.
As stated in the comments, you need a better uncoupling of your code.
You need, for example, some kind of "dependency injection" to allow for such a uncoupling.
Here is a simple example of how it can be done :
public class ClassThatUsesYourBankApi
{
private readonly IBankApi _api;
// the constructor will be given a reference to the interface
public ClassThatUsesYourBankApi (IBankApi api)
{
// here you could check for null parameter and throw exception as needed
this._api = api;
}
// this method can now be tested with the mock interface
public void MethodThatUseTheApi()
{
int result = this._api.pay();
if (result == 1)
{
// some things that happens
}
else
{
// some other thing
}
}
}
How to unit test that method :
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class TestMyMethod
{
[TestMethod]
public void MyMethod_WithBankApiReturns1_ShouldHaveThingsThatHappens()
{
// Arrange
var apiMock = new Mock<IBankApi>();
apiMock.Setup(api => api.pay())
.Returns(1);
var myObject = new ClassThatUsesYourBankApi(apiMock.Object);
// Act
int result = myObject.MethodThatUseTheApi();
// Assert
// Here you test that the things that should have happened when the api returns 1 actually have happened.
}
}
The key thing to understand here, is that you must not instantiate the api you need to mock in the method you want to test
In other words, "uncoupling" your method with your api is done by programming to an interface, and code such as you don't have
var api = new BankApi()
directly in the method you want to unit test.
I showed a way to do that, and there are other.

IQueryable Unit or Integration Test

I have a web api and I am exposing a endpoint like so:
api/Holiday?name={name}
This is the controller get method for the web api:
public IQueryable<Holiday> GetHolidayByName(string name)
{
return db.Holiday.Where(n => string.Equals(n.Name, name));
}
How can I write a unit/integration test for this that checks the names are equal? I can check the result is not null however bit confused how I can check the names are equal:
[TestMethod]
public void GetHoliday_GetHolidayByName()
{
// Arrange
HolidaysController controller = new HolidaysController();
// Act
IQueryable<Holiday> actionResult = controller.GetHolidayByName("Spain");
//Assert
Assert.IsNotNull(actionResult);
//any attempt to check names are equal results in a fail
//For instance this fails
var result = controller.GetHolidayByName("Spain") as OkNegotiatedContentResult<Holiday>;
Assert.AreEqual("Spain", result.Content.Name);
}
The test would look like this where you can use linq to verify that all the result returned satisfy your criteria.
[TestMethod]
public void GetHoliday_GetHolidayByName()
{
// Arrange
string name = "Spain";
HolidaysController controller = new HolidaysController();
// Act
IQueryable<Holiday> actionResult = controller.GetHolidayByName(name);
//Assert
Assert.IsNotNull(actionResult);
Assert.IsTrue(actionResult.All(n => string.Equals(n.Name, name));
}
The assumption here is that the db will provide you with the test data you want. Otherwise you will have to make some design changes to allow for providing mocked/fake data.
If you are connecting to an actual database then this is more an integration test rather than a unit test.
public interface IDbRepository
{
IQueryable<Holiday> GetHolidayByName(string name)
}
public class DbRepository : IDbRepository
{
public IQueryable<Holiday> GetHolidayByName(string name)
{
return db.Holiday.Where(n => string.Equals(n.Name, name));
}
}
private IDbRepository _dbRepository;//initialize, preferably through construtor
public IQueryable<Holiday> GetHolidayByName(string name)
{
return _dbRepository.GetHolidayByName(name)
}
First of all, I think that you should be testing db results but objects. Mock your method to give you "Holiday" Items, then override the "equals" method on the object, or just comparte the properties you need to check

Unit Testing a controller that uses windows authentication

-------Please see updates below as I now have this set up for dependency injection and the use of the MOQ mocking framework. I'd still like to split up my repository so it doesn't directly depend on pulling the windowsUser within the same function.
I have a Web API in an intranet site that populates a dropdown. The query behind the dropdown takes the windows username as a parameter to return the list.
I realize I don't have all of this set up correctly because I'm not able to unit test it. I need to know how this "should" be set up to allow unit testing and then what the unit tests should look like.
Additional info: this is an ASP.NET MVC 5 application.
INTERFACE
public interface ITestRepository
{
HttpResponseMessage DropDownList();
}
REPOSITORY
public class ExampleRepository : IExampleRepository
{
//Accessing the data through Entity Framework
private MyDatabaseEntities db = new MyDatabaseEntities();
public HttpResponseMessage DropDownList()
{
//Get the current windows user
string windowsUser = HttpContext.Current.User.Identity.Name;
//Pass the parameter to a procedure running a select query
var sourceQuery = (from p in db.spDropDownList(windowsUser)
select p).ToList();
string result = JsonConvert.SerializeObject(sourceQuery);
var response = new HttpResponseMessage();
response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");
return response;
}
}
CONTROLLER
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
public ExampleController()
{
_exampleRepository = new ExampleRepository();
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
UPDATE 1
I have updated my Controller based on BartoszKP's suggestion to show dependency injection.
UPDATED CONTROLLER
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
//Dependency Injection
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
UPDATE 2
I have decided to use MOQ as a mocking framework for unit testing. I'm able to test something simple, like the following. This would test a simple method that doesn't take any parameters and doesn't include the windowsUser part.
[TestMethod]
public void ExampleOfAnotherTest()
{
//Arrange
var mockRepository = new Mock<IExampleRepository>();
mockRepository
.Setup(x => x.DropDownList())
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
ExampleController controller = new ExampleController(mockRepository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var response = controller.DropDownList();
//Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
I need help testing the DropDownList method (one that does include code to get the windowsUser). I need advice on how to break this method apart. I know both parts shouldn't been in the same method. I don't know how to arrange splitting out the windowsUser variable. I realize this really should be brought in as a parameter, but I can't figure out how.
You usually do not unit-test repositories (integration tests verify if they really persist the data in the database correctly) - see for example this article on MSDN:
Typically, it is difficult to unit test the repositories themselves, so it is often better to write integration tests for them.
So, let's focus on testing only the controller.
Change the controller to take IExampleRepository in its constructor as a parameter:
private IExampleRepository _exampleRepository;
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
Then, in your unit tests, use one of mocking frameworks (such as RhinoMock for example) to create a stub for the sole purpose of testing the controller.
[TestFixture]
public class ExampleTestFixture
{
private IExampleRepository CreateRepositoryStub(fake data)
{
var exampleRepositoryStub = ...; // create the stub with a mocking framework
// make the stub return given fake data
return exampleRepositoryStub;
}
[Test]
public void GivenX_WhenDropDownListIsRequested_ReturnsY()
{
// Arrange
var exampleRepositoryStub = CreateRepositoryStub(X);
var exampleController = new ExampleController(exampleRepositoryStub);
// Act
var result = exampleController.DropDownList();
// Assert
Assert.That(result, Is.Equal(Y));
}
}
This is just a quick&dirty example - CreateRepositoryStub method should be of course extracted to some test utility class. Perhaps it should return a fluent interface to make the test's Arrange section more readable on what is given. Something more like:
// Arrange
var exampleController
= GivenAController()
.WithFakeData(X);
(with better names that reflect your business logic of course).
In case of ASP.NET MVC, the framework needs to know how to construct the controller. Fortunately, ASP.NET supports the Dependency Injection paradigm and a parameterless constructor is not required when using MVC unity.
Also, note the comment by Richard Szalay:
You shouldn't use HttpContext.Current in WebApi - you can use base.User which comes from HttpRequestBase.User and is mockable. If you really want to continue using HttpContext.Current, take a look at Mock HttpContext.Current in Test Init Method
One trick that I find very useful when trying to make old code testable when said code is accessing some global static or other messy stuff that I can't easily just parameterize is to wrap access to the resource in a virtual method call. Then you can subclass your system under test and use that in the unit test instead.
Example, using a hard dependency in the System.Random class
public class Untestable
{
public int CalculateSomethingRandom()
{
return new Random().Next() + new Random().Next();
}
}
Now we replace var rng = new Random();
public class Untestable
{
public int CalculateSomethingRandom()
{
return GetRandomNumber() + GetRandomNumber();
}
protected virtual int GetRandomNumber()
{
return new Random().Next();
}
}
Now we can create a testable version of the class:
public class Testable : Untestable
{
protected override int GetRandomNumber()
{
// You can return whatever you want for your test here,
// it depends on what type of behaviour you are faking.
// You can easily inject values here via a constructor or
// some public field in the subclass. You can also add
// counters for times method was called, save the args etc.
return 4;
}
}
The drawback with this method is that you can't use (most) isolation frameworks to implement protected methods (easily), and for good reason, since protected methods are sort of internal and shouldn't be all that important to your unit tests. It's still a really handy way of getting things covered with tests so you can refactor them, instead of having to spend 10 hours without tests, trying to do major architectual changes to your code before you get to "safety".
Just another tool to keep in mind, I find it comes in handy from time to time!
EDIT: More concretely, in your case you might want to create a protected virtual string GetLoggedInUserName(). This will technically speaking keep the actual call to HttpContext.Current.User.Identity.Name untested, but you will have isolated it to the simplest smallest possible method, so you can test that the code is calling the correct method the right amount of times with the correct args, and then you simply have to know that HttpContext.Current.User.Identity.Name contains what you want. This can later be refactored into some sort of user manager or logged in user provider, you'll see what suits best as you go along.

Mocked Object Still Making Calls to Service

So I'm writing tests for our MVC4 application and I'm testing Controller actions specifically. As I mention in the title, the test still hits the service (WCF) instead of returning test data. I have this controller:
public class FormController : Controller
{
public SurveyServiceClient Service { get; set; }
public SurveyDao Dao { get; set; }
public FormController(SurveyServiceClient service = null, SurveyDao dao = null)
{
this.Service = service ?? new SurveyServiceClient();
this.Dao = dao ?? new SurveyDao(Service);
}
//
// GET: /Form/
public ActionResult Index()
{
var formsList = new List<FormDataTransformContainer>();
Dao.GetForms().ForEach(form => formsList.Add(form.ToContainer()));
var model = new IndexViewModel(){forms = formsList};
return View("Index", model);
}
And it uses this DAO object:
public class SurveyDao
{
private readonly SurveyServiceClient _service;
private readonly string _authKey;
public SurveyDao(SurveyServiceClient serviceClient)
{
_service = serviceClient;
}
....
public FormContract[] GetForms()
{
var forms = _service.RetrieveAllForms();
return forms;
}
And this is my test using JustMock, the mock on GetForms() returns some test data in a helper class:
[TestClass]
public class FormControllerTest
{
private SurveyDao mockDao;
private SurveyServiceClient mockClient;
public FormControllerTest()
{
mockClient = Mock.Create<SurveyServiceClient>();
mockDao = Mock.Create<SurveyDao>(mockClient);
}
[TestMethod]
public void TestIndexAction()
{
//Arrange
var controller = new FormController(mockClient, mockDao);
Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper);
//Act
var result = controller.Index() as ViewResult;
//Assert
Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel));
}
}
My problem is that when I run the test, the Service is still being called. I've verified this using Fiddler as well as debugging the test and inspecting the value of "result" which is populated with our service's test data.
EDIT:
I've changed the test constructor to be a [TestInitialize] function, so the Test now looks like this:
[TestClass]
public class FormControllerTest
{
private SurveyDao mockDao;
private SurveyServiceClient mockClient;
[TestInitialize]
public void Initialize()
{
mockClient = Mock.Create<SurveyServiceClient>();
mockDao = Mock.Create<SurveyDao>(Behavior.Strict);
}
[TestMethod]
public void TestIndexAction()
{
//Arrange
var controller = new FormController(mockClient, mockDao);
Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper);
//Act
var result = controller.Index() as ViewResult;
//Assert
Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel));
}
}
Please verify that you are using the correct assembly for JustMock. There are a few different ones (VisualBasic, Silverlight, JustMock). The JustMock one is the one you should be including in your project.
Failure to include the correct one will cause the behavior that you are describing (method not being properly stubbed).
The JustMock manual explains (highlights by me):
By default Telerik JustMock uses loose mocks and allows you to call
any method on a given type. No matter whether the method call is
arranged or not you are able to call it.
You can control this behavior when calling the Create() method of you Mock:
var foo = Mock.Create<IFoo>(Behavior.Strict);
There you can specify what the mock object should do if you have not explicitly implemented a certain method. In your case (I think it is the default behavior) the mock indeed calls the original method on the object that you want to mock.
You have the following choices in the Behavior Enumeration enumeration:
Loose: Specifies that by default mock calls will behave like a stub, unless explicitly setup.
RecursiveLoose: Specifies that by default mock calls will return mock objects, unless explicitly setup.
Strict: Specifies that any calls made on the mock will throw an exception if not explictly set.
CallOriginal: Specifies that by default all calls made on mock will invoke its corresponding original member unless some expecations are set.

Unit Testing Interfaces with Moq

I'm new to Moq and unit testing. I have been doing a unit test and this is the following code:
private Mock<IServiceAdapter> repository;
[TestInitialize]
public void Initialize()
{
repository= new Mock<IServiceAdapter>();
}
[TestMethod()]
public void SaveTest()
{
//Setup
string Name = "Name1";
string Type = "1";
string parentID = null;
repository.Setup(x => x.Save(Name , Type, parentID)).Returns("Success").Verifiable();
//Do
var result = repository.Object.Save(Name , Type, parentID);
//Assert
repository.Verify();
}
My problem is that the test will always return the string that I put in the Returns parameter, in other words, it will always return "success" or whatever I write in its place. I guess thats not right because thats not the real behavior of the service. Anyone knows how I can mirror the real behavior of the "Save" service I'm trying to test? So lets say, if the return string is different from the service method,then the test should fail.
Edited
The ServiceAdapter interface its just a wrapper for a Web Service which I call like a REST Service. It's a Web Forms Project.
I'm doing something like in this post
How to mock a web service
Should I create something like a FakeController with Dependency Injection to make it work?
You are testing mock here, which gives you nothing (because this mock is not used in your real application). In unit-testing you should create and test your real objects, which exist in your real application (i.e. interface implementations). Mocks used for mocking dependencies of objects under test.
So, mock of service adapter will be useful for tests of object, which uses that adapter, e.g. some controller tests:
private FooController _controller; // object under test, real object
private Mock<IServiceAdapter> _serviceAdapter; // dependency of controller
[TestInitialize]
public void Initialize()
{
_serviceAdapter = new Mock<IServiceAdapter>();
_controller = new FooController(_serviceAdapter.Object);
}
[TestMethod()]
public void SaveTest()
{
// Arrange
string name = "Name1";
string type = "1";
string parentID = null;
_serviceAdapter.Setup(x => x.Save(name , type, parentID))
.Returns("Success").Verifiable();
// Act on your object under test!
// controller will call dependency
var result = _controller.Bar(name , type, parentID);
// Assert
Assert.True(result); // verify result is correct
_serviceAdapter.Verify(); // verify dependency was called
}

Categories