I am trying to include Unit testing to my Xamarin PCL project.
This is what I am basically doing :
Login Page class :
public bool isUserRemembered()
{
return DependencyService.Get<IUserDefaults>().getUserRemembered();
}
public void setRememberUser(bool check)
{
DependencyService.Get<IUserDefaults>().setUserRemembered(check);
}
UnitTest class (iOS) :
[Test]
public void RememberKeyTrueTest()
{
LoginPage page = new LoginPage();
bool isRemember = true;
page.setRememberUser(isRemember);
bool value = page.isUserRemembered();
if (value)
Pass();
else
Fail();
}
I get Null Reference Exception on this line : DependencyService.Get<IUserDefaults>().setUserRemembered(check).
Will dependency service work with unit testing? Or is there any work around it?
When I use Dependency Injection in my code, I use IoC (Inversion Of Control) to handle the creation of the dependencies in my production code, and manually create my dependencies in my unit tests.
My main reason for this is that it is explicit. Often I'll be using a Mocking framework to create fake instances so I don't want the extra complexity.
A suggestion on your code under test, you have swapped a dependency to your class for a dependency on your DependencyService. I'm not saying don't use the DependencyService but you could pass in the dependency to your constructor of the class. Then your test could pass in a fake instance and the production code would use the DependencyService to get you an IUserDefaults and pass it in. That would make your class easier to test.
Related
I have a class Library project which will be consumed by some legacy code and some modernized code. briefly I would like to show what issues I am facing with.
class ClasslibraryService
{
private Dependency1 _dependency1;
private Dependency2 _dependency2
public ClasslibraryService(Dependency1 dependency)
{
_dependency1 = dependency;
// this dependency2 could be something like logger or Bearer token service which I do not want to expose to consuming application
_dependency2 = new Dependency2(new Dependency3());
}
public int DoSomeOperation()
{
var res = _dependency2.DoSomething();
return _dependency1.DoSomeOperation(res);
}
}
So basically I had to new up within constructor without injecting dependency using constructor.
Now while unit test this class , I have created another constructor which takes all dependency through constructor. This is working fine.
But question here is
I know I am violating main objective of unit testing by creating another constructor.Actual code will not be using this constructor. But I could not find any other way too!!
If 1 is not correct solution , please suggest me one solution
TIA
I know I am violating main objective of unit testing by creating
another constructor.Actual code will not be using this constructor.
But I could not find any other way too!!
I know this is heresy for some but I believe there's no hard rule in software development. It's a game of tradeoffs. If it's too expensive to change how your constructor works, you can probably do something like this for now:
public ClasslibraryService(Dependency1 dependency1, Dependency2 dependency2 = null)
{
_dependency1 = dependency1;
_dependency2 = dependency2 ?? new Dependency2(new Dependency3());
}
This introduces a default implementation for real code which can be overridden in unit tests. You can then revisit this code later and make it purer.
Following this prototype for unit testing I've ran into a problem when using JS interop.
[Test]
public void ExampleTest()
{
var component = host.AddComponent<MyComponent>();
}
Just adding a component that uses IJSRuntime will cause the following exception
System.InvalidOperationException : Cannot provide a value for property 'JsRuntime' on type 'Application.Components.MyComponent'. There is no registered service of type 'Microsoft.JSInterop.IJSRuntime'.
The JS interop isn't doing anything of interest, it's just a void function that focuses an element - I don't care about testing it, I just want to be able to proceed with writing tests for the component itself.
How can I use Moq to mock IJSRuntime?
When I try something like
[Test]
public void ExampleTest()
{
var jsRuntimeMock = new Mock<IJSRuntime>();
host.AddService(jsRuntimeMock);
var component = host.AddComponent<MyComponent>();
}
I still get the exception
host.AddService(jsRuntimeMock);
registers Mock<IJSRuntime> as a dependency.
No classes in the implementation (outside of a test assembly) should have such a dependency but it's a common error to make.
Register IJSRuntime as a dependency using the Mock<T> property Object, which contains a reference to an object that implements the interface.
Like this:
host.AddService(jsRuntimeMock.Object);
Microsoft uses a lot of internal Singletons and therefore having test on application Level very very difficult and you should replace all Default Services like IJSRuntime, NavigationManager and NavigationInterceptor. I hope in the next preview there will be an easy way to create a unittest methods and simulate the browser.
I have a Unit Test project & want to shim-in Stub implementations for the repositories within a Unit of Work class. I would know how to do it using other IoC technologies, but am new to StructureMap.
How do I redefine & substitute a definition from inside my Unit Test project
What does that look like?
I'm having trouble finding good documentation on this.
DEFAULT CONTAINER:
Below is part of the business registry I hope to override.
public ContainerRegistry()
{
Scan(...);
// --------
// UNIT OF WORK
// This is the DEFAULT implementation
For(typeof(IRepository<>)).Use(typeof(GenericRepository<>));
For<IUnitOfWork>().Use<MeasurementContractsUnitOfWork>();
}
FOR UNIT TESTS:
In the unit test project I want IoC to use this instead:
// This is the STUB Implementation
For(typeof(IRepository<>)).Use(typeof(GenericRepositoryStub<>));
THE OBJECTIVE:
The objective is to simply use the container, as normal, but get the STUB shimmed-in AUTOMATICALLY.
var container = IoC.Initialize();
var uow = container.GetInstance<IUnitOfWork>()
I am unsure if this is the right way to do it, but this is how I accomplished my goal. If someone gives a better answer, I will mark theirs as correct:
I created separate IOC Initializer & ContainerRegistry classes within the Unit Test project, like so...
INITIALIZER CLASS:
public static class IoC
{
public static IContainer Initialize()
{
var container = new Container();
// NOTE: If you have many Registries to consider, you can add them (order matters)
// The Business Registry
container.Configure(x => x.AddRegistry<Business.DependencyResolution.ContainerRegistry>());
// The UnitTest Projects Registry (order matters)
container.Configure(x => x.AddRegistry<ContainerRegistry>());
return container;
}
}
REGISTRY CLASS:
public class ContainerRegistry : Registry
{
public ContainerRegistry()
{
// The Override
For(typeof(IRepository<>)).Use(typeof(GenericRepositoryIdentifiableStub<>));
}
}
Consider this class with these two constructors:
public class DocumentService
{
private IDocumentDbService documentDbService;
private IDirectoryService directoryService;
private IFileService fileService;
// Constructor
public DocumentService()
{
this.documentDbService = new DocumentDbService();
this.directoryService = new DirectoryInfo();
this.filService = new FileInfo();
}
// Injection Constructor
public DocumentService(IDocumentDbService dbs, IDirectoryService ds, IFileService fs)
{
this.documentDService = dbs;
this.directoryService = ds;
this.fileService = fs;
}
}
I use the second constructor to mock the dependencies for unit testing.
Some times there are too many dependencies, so the injection constructor would have too many parameters.
So, I want to use Unity dependency injection.
Question
How can I refactor this code to use Unity instead?
(After reading Unity documents, still not sure how to use it correctly on my codes.)
Assuming you want to simplify unit test code to avoid manually setting up each dependency in every test:
You can setup container and add all necessary mocks there and than Resolve you class for the test like:
// that initialization can be shared
var container = new UnityContainer();
// register all mocks (i.e. created with Moq)
container.RegisterInstnce<IDocumentDbService>(Mock.Of<IDocumentDbService> ());
// resolve your class under test
var documentService = container.Resolve<DocumentService>();
Assert.AreEqual(42, documentService.GetSomething());
I quess you want to inject dependencies in both situations: in (unit)tests (e.g. using RhinoMocks) and real implementation (using Unity). The refactoring implies in that case that you should remove the the first constructor (of class DocumentService). Needed configuration in your dependencies should be loaded inside the dependency itself: DocumentDbService, DirectoryInfo, FileInfo. More information (like Dependency Injection Lifecycle) and some examples are available on MSDN, see https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx
I'm trying to test my service using ninject and an unit test project with visual studio 2012. My inject works ok on my controllers, but when I try to do the same in the unit test class I get an Exception.
System.NullReferenceException: Object reference not set to an instance of an object.
namespace Trex.UnitTests
{
[TestClass]
public class GiftServiceTests
{
private IGiftService _giftService;
public void GiftServiceTest(IGiftService giftService)
{
_giftService = giftService;
}
[TestMethod]
public void AddGift()
{
var list = _gift.FindAll(); <--- this line throw an exception
}
}
}
I think there is something wrong with the injection but I dont get it.
It looks to me like a typo of _giftService. In addition, attribute [TestInitialize] needs to be used in your constructor.
Try the following code by placing the correct service name _giftService - that your code is injecting instead:
var list = __giftService.FindAll();
Edit: Unit testing should be done without Ninject. Just create an instance of the object under test and inject a mock for every dependency manually.
Here is a sample with [TestInitialize]:
The unit test must have a default constructor:
[TestClass]
public class TestControllersHomeController
{
private HomeController _sut;
[TestInitialize]
public void MyTestInitialize()
{
var kernel = NinjectWebCommon.CreatePublicKernel();
_sut = kernel.Resolve<HomeController>();
}
[TestMethod]
public void TestIndex()
{
var result = _sut.Index();
Assert.IsNotNull(result);
}
}
The only way dependency injection is able to call your constructor and fill it with a parameter that has a value is if the dependency injection kernel is the one that instantiates your class.
In your case, MSTest is instantiating your test class, so Ninject does not have a chance to call your constructor.
To be honest, you are going about this the wrong way. You will battle MSTest if you pursue this further to try to get Ninject (or any other DI framework) to instantiate your test classes.
I would recommend you use 'new' to instantiate the class under test (_giftService = new GiftService();). If that class has dependencies in its constructor, use a mocking framework to pass in mocked version of those dependencies. This way you isolate your unit tests to only the functionality of the class under test.
_gift is null. Your variable is _giftService. You also should use the [TestInitialize] attribute for your constructor.
Extra tip:
You shouldn't create any dependencies in your unit test. So the giftService which you want to use should be a mock or a stub.