Run integration test against two providers - c#

I'm new to C# and trying to write an integration test for a service. The service uses 2 providers as example below, and I don't know how to include them in my test. I'm using xUnit.
// Service
namespace App.Services
{
public interface IProvider
{ }
public class FirstProvider : IProvider
{ }
public class SecondProvider : IProvider
{ }
public class AppManager
{
private readonly IEnumerable<IProvider> _providers;
public AppManager(
IEnumerable<IProvider> providers)
{
_providers = providers;
}
public asyn Task ListItems()
{
foreach (var singleProvider in _providers) // When running test, I got ERROR here: _providers is null)
{
// do something
}
}
}
}
// Test
public class AppManagerTest
{
private readonly IEnumerable<IProvider> _providers;
[Fact]
public async ListItems()
{
// Arrange
var sut = new AppManager(_providers);
// Act
// Assert
}
}
When running test, I got an error as pointed above in my service code. The error is System.NullReferenceException : Object reference not set to an instance of an object. Debugging the test shows that _providers is null.
So as I understood, my test does not get any of the providers. What should I do here?

Related

DataService in Test env always return null when fetching InMemoryDb data

public class TestStartup : Startup
{
private readonly Mock<ICarService> _carServiceMock;
public TestStartup(IConfiguration configuration) : base(configuration)
{
_carServiceMock = new Mock<ICarService>();
}
public override void ConfigureMyServices(IServiceCollection services)
{
services.AddSingleton(_carServiceMock.Object);
}
public override void ConfigureDatabase(IServiceCollection services)
{
services.AddDbContext<CarContext>(options => options.UseInMemoryDatabase("CarDb"));
services.AddTransient<DataSeed>();
}
}
public class TestFixture: IDisposable, ICollectionFixture<TestFixture>
{
public TestFixture()
{
_server = new TestServer(new WebHostBuilder()
.UseStartup<TestStartup>()
.UseEnvironment("Development"));
_client = _server.CreateClient();
}
}
Inside Controller I'm using ICarService which is using CarContext to retrieve data from the Db.
public class CarController
{
private readonly ICarService _carService;
public CarController(ICarService carService)
{
_carService = carService;
}
[HttpGet]
public async Task<IActionResult> Get([FromRoute] int id)
{
var contact = await _carService.GetAsync(id); **// this is always null**
}
}
My question is:
Since this is an integration test, do I need to mock ICarService in the first place and if so, what I'm doing wrong here?
If you are testing how the CarService class interacts with the database then you shouldn't be mocking it.
What you want to do is use the real CarService implementation and let dependency injection add the InMemoryDatabase into that class as the CarContext parameter.
So, remove the Mock<ICarService> and register the real one instead.
Why is it returning null?
In you example, when you call the method _carService.GetAsync(id) it is calling the mock class. But you haven't Setup any methods on the mock so any calls will return null.
You need to add the following to cause the mocked method to return a value:
_carService.Setup(cs => cs.GetAsync(It.IsAny<int>()).Returns(1);
But this would not call the in memory database as you are using a mock for CarService.

Create class and auto-initialize dependencies with FakeItEasy

Is it possible to create a class under test with FakeItEasy, where all dependencies that are declared in the constructor are initialized automatically with fakes?
Imagine the class:
public class Inserting
{
public Inserting(
ITransactionService transactionService,
ISharedData sharedData)
{
TransactionService = transactionService;
SharedData = sharedData;
}
public ITransactionService TransactionService { get; }
public ISharedData SharedData { get; }
public void Enter()
{
TransactionService.StartTransaction();
}
}
Then I am creating all fake-objects in the test setup and construct my class under test with those fakes:
public class InsertingTest
{
private Inserting _inserting;
private ISharedData _fakeSharedData;
private ITransactionService _fakeTransactionService;
[SetUp]
public void SetUp()
{
_fakeTransactionService = A.Fake<ITransactionService>();
_fakeSharedData = A.Fake<ISharedData>();
_inserting = new Inserting(_fakeTransactionService, _fakeSharedData);
}
[Test]
public void TestEnter()
{
// Arrange
// Act
_inserting.Enter();
// Assert
A.CallTo(() => _fakeTransactionService.StartTransaction().MustHaveHappened();
}
}
But I saw in the Java-world, that when using Mockito and Dagger 2, you can do something like this:
public class PhoneDialer {
private Activity activity;
private PhoneCallListener phoneCallListener;
#Inject
public PhoneDialer(Activity activity, PhoneCallListener phoneCallListener) {
this.activity = activity;
this.phoneCallListener = phoneCallListener;
}
}
public class PhoneDialerTest {
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Mock
PhoneCallListener phoneCallListener;
#Mock
Activity activity;
#InjectMocks
PhoneDialer dialer;
#Test
public void test_dialer() throws Exception {
// Arrange
// Act
dialer.callNumber("abc");
// Assert
Mockito.verify(phoneCallListener, times(1)).startCall();
}
}
and the mocked classes are initialized automatically with fakes. Is there an equivalent procedure or function in C# with FakeItEasy?
I think you want something like
Automatically inject fakes in test fixture with FakeItEasy. You use [Fake] to mark fakes to inject and [UnderTest] to mark the production type to test.
We really should put this into the documentation.
Alternatively,
AutoFixture has an AutoFixture.AutoFakeItEasy module,
there's Autofac FakeItEasy integration, and also
Ninject FakeItEasy integration
I saw 'Automatically inject fakes in text fixture with FakeItEasy' and my initial reaction was surprise that it differed from my preconception, mainly because it needs 'intrusive' changes that attribute the test code... but perhaps that is an overreaction.
The FakeAttribute and UnderTestAttribute do force what is potentially a good structural constraint on your test (and system) design...
[FWLIW, before googling this, I had imagined the following:
containerBuilder.RegisterAsFakeCallingBaseType<SystemUnderTest>();
You can do something like this with Autofac's registration sources.
using Autofac;
using Autofac.Core;
using Autofac.Core.Activators.Delegate;
using Autofac.Core.Lifetime;
using Autofac.Core.Registration;
using FakeItEasy;
using Xunit;
public interface IDependOnSomething { }
public class IImplementThat : IDependOnSomething { }
public class CanIResolveIt
{
public CanIResolveIt(IDependOnSomething it)
{
}
}
public class FakeRegistrationSourceTest
{
[Fact]
public void BasicTest()
{
var container = new ContainerBuilder();
container.RegisterTypes<IImplementThat>().As<IDependOnSomething>();
container.RegisterSource(new FakeRegistrationSource<CanIResolveIt>());
var c = container.Build();
var theFake = c.Resolve<CanIResolveIt>();
Assert.NotNull(theFake);
}
}
public class FakeRegistrationSource<T> : IRegistrationSource
where T : class
{
public bool IsAdapterForIndividualComponents => false;
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if (swt == null || !typeof(T).IsAssignableFrom(swt.ServiceType)) // TODO: is this the right way around?
{
return Enumerable.Empty<IComponentRegistration>();
}
var registration = new ComponentRegistration(
Guid.NewGuid(),
new DelegateActivator(swt.ServiceType, (context, #params) =>
{
List<object> v = new List<object>();
foreach (ParameterInfo p in typeof(T).GetConstructors().Single().GetParameters())
{
v.Add(context.Resolve(p.ParameterType));
}
return A.Fake<T>(that => that.CallsBaseMethods().WithArgumentsForConstructor(v));
}),
new CurrentScopeLifetime(),
InstanceSharing.None,
InstanceOwnership.OwnedByLifetimeScope,
new[] { service },
new Dictionary<string, object>());
return new IComponentRegistration[] { registration };
}
}
Main advantage of this approach is that it knows how to instantiate fake objects subclassing classes with constructor parameters, and inheriting their default behavior, when they have a single constructor (choosing intelligently from multiple constructors would be an obvious challenge that I'm not going to tackle...)
An obvious drawback is explicit registration every time you want something faked. AutoFake and so on offer ways to overcome that with faking of just about everything by default, which might well be what you want... and you can override it if not.]

How do I get fake path for HttpContext.Current.Server.MapPath which is assigned to protected object inside method unit testing?

I am new to unit test, MSTest. I get NullReferenceException.
How do I set HttpContext.Current.Server.MapPath for doing unit test?
class Account
{
protected string accfilepath;
public Account(){
accfilepath=HttpContext.Current.Server.MapPath("~/files/");
}
}
class Test
{
[TestMethod]
public void TestMethod()
{
Account ac= new Account();
}
}
HttpContext.Server.MapPath would require an underlying virtual directory provider which would not exist during the unit test. Abstract the path mapping behind a service that you can mock to make the code testable.
public interface IPathProvider {
string MapPath(string path);
}
In the production implementation of the concrete service you can make your call to map the path and retrieve the file.
public class ServerPathProvider: IPathProvider {
public MapPath(string path) {
return HttpContext.Current.Server.MapPath(path);
}
}
you would inject the abstraction into your dependent class or where needed and used
class Account {
protected string accfilepath;
public Account(IPathProvider pathProvider) {
accfilepath = pathProvider.MapPath("~/files/");
}
}
Using your mocking framework of choice or a fake/test class if a mocking framework is not available,
public class FakePathProvider : IPathProvider {
public string MapPath(string path) {
return Path.Combine(#"C:\testproject\",path.Replace("~/",""));
}
}
you can then test the system
[TestClass]
class Test {
[TestMethod]
public void TestMethod() {
// Arrange
IPathProvider fakePathProvider = new FakePathProvider();
Account ac = new Account(fakePathProvider);
// Act
// ...other test code
}
}
and not be coupled to HttpContext
You can create another constructor that takes a path as parameter. That way you can pass a fake path for unit testing

How can I pass a mock object when I am doing setter injection in ASP.NET MVC Controller

Say, I have the below Controller
public class UsersController : Controller
{
private IUsersRepository UsersRepository { get; }
public UsersController()
{
UsersRepository = DependencyResolver.Current.GetService(typeof(IUsersRepository)) as IUsersRepository;
}
public ActionResult Index ()
{
MyUserDefinedModel data = UsersRepository.MyRepository();
return View(data);
}
}
Now I want to mock the IUsersRepository and pass it to the controller in my test script.
Below my test code
public class UsersListTest
{
private UsersController usersController = new Mock<IUsersRepository>();
private Mock<IUsersRepository> usersRepository = new UsersController();
[TestMethod]
public void TestMethod1()
{
//usersRepository.Setup(x => x.Get()).Returns(users);
}
}
As because private IUsersRepository UsersRepository { get; } private, I'm not able to pass the mock of IUsersRepository.
What would be the good idea to write unit test and mock in such case.
The reason that you have trouble with testing is because your Controller class uses the Service Locator anti-pattern. A Service Locator is a either a global instance (the DependencyResolver.Current) or an abstraction that allows resolving dependencies at runtime. One of the many downsides of the Service Locator is the problems it causes with testing.
You should move away from the Service Locator pattern and use dependency injection instead, favorably constructor injection. Your application components should have a single public constructor and those constructors should do nothing more than storing the incoming dependencies. This will result in the following UsersController implementation:
public class UsersController : Controller
{
private IUsersRepository usersRepository;
public UsersController(IUsersRepository usersRepository)
{
this.usersRepository = usersRepository;
}
public ActionResult Index()
{
return View(this.usersRepository.MyRepository());
}
}
With this in place, unit testing became trivial:
public class UsersControllerTests
{
[TestMethod]
public void Index_Always_CallsRepository()
{
// Arrange
var repository = new Mock<IUsersRepository>();
var controller = CreateValidUsersController(repository.Instance);
// Act
var result = controller.Index();
// Assert
Assert.IsTrue(repository.IsCalled);
}
// Factory method to simplify creation of the class under test with its dependencies
private UsersController CreateValidUsersController(params object[] deps) {
return new UsersController(
deps.OfType<IUsersRepository>().SingleOrDefault() ?? Fake<IUsersRepository>()
// other dependencies here
);
}
private static T Fake<T>() => (new Mock<T>()).Instance;
}
This does however, force you to change MVC's default IControllerFactory, since out-of-the-box, MVC can only handle controllers with a default constructor. But this is trivial and looks as follows:
public sealed class CompositionRoot : DefaultControllerFactory
{
private static string connectionString =
ConfigurationManager.ConnectionStrings["app"].ConnectionString;
protected override IController GetControllerInstance(RequestContext _, Type type) {
if (type == typeof(UsersController))
return new UsersController(new UsersRepository());
// [other controllers here]
return base.GetControllerInstance(_, type);
}
}
Your new controller factory can be hooked into MVC as follows:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start() {
ControllerBuilder.Current.SetControllerFactory(new CompositionRoot());
// the usual stuff here
}
}
You can find a more complete example here.
You could add a constructor that allows you to supply a mock of IUsersRepository. Your default constructor would call this with the instance from the DependencyResolver, like this:
public class UsersController : Controller
{
private IUsersRepository UsersRepository { get; }
public UsersController(IUsersRepository usersRepository)
{
UsersRepository = usersRepository;
}
public UsersController():this(DependencyResolver.Current.GetService(typeof(IUsersRepository)) as IUsersRepository)
{
}
public ActionResult Index ()
{
MyUserDefinedModel data = UsersRepository.MyRepository();
return View(data);
}
}

ServiceStack Unit test- serviceStack Response object is not initializing

I have used Nunit framework to write Unit test for ServiceStack apis.
code as below
public class AppHost : AppHostBase
{
public AppHost()
: base("SearchService", typeof(SearchService).Assembly)
{
}
}
Service class as below
public class SearchService:Service
{
public SearchResponse Get(SearchRequest request)
{
// to stuff
Response.StatusCode = (int)HttpStatusCode.OK;
return SearchReponse;
}
}
unit test class as below
[TestFixture]
public class SearchServiceTests
{
private readonly ServiceStackHost appHost;
public SearchServiceTests()
{
appHost = new BasicAppHost(typeof(SearchService).Assembly)
{
}.Init();
}
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
appHost.Dispose();
}
[Test]
public void TestMethod1()
{
var service = appHost.Container.Resolve<SearchService>();
var r= service.Get(new SearchRequest());
Assert.That(r, Is.Not.Null);
}
}
I am getting null reference exception for Response object. When I hit server using any client (postman or rest client) that response object is getting initialised but through unit test Response object is not getting initialised, can anyone tell me why is it happening?
Thanks in advance.
need to mock request object .so that service layer will initialise response object.
following code change worked for me.
var service = appHost.Container.Resolve<SearchService>();
service.Request = new MockHttpRequest();
then make service method call.

Categories