I am unit-testing an async method that returns a List<T>. This method has a dependency on a mapping class/interface. In my unit-test, I am mocking the mapping class using moq. The test runs okay, and the returned list has items, but the values of the items is null. I think the problem is because I haven't stubbed-out the mapping classes methods properly. I don't have a lot of experience with testing, so any guidance is appreciated.
Test Method:
[TestMethod]
[TestCategory("CSR.Data.Tests.Services.ServiceSearchTest")]
public void SearchAccount()
{
// Arrange
var mapper = new Mock<CSR.Data.Mapping.Interfaces.IMapper<Account, AccountDTO>>();
mapper.Setup(i => i.Initialize());
mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(It.IsAny<Account>);
mapper.Setup(i => i.DomainToDto(It.IsAny<Account>())).Returns(It.IsAny<AccountDTO>);
var service = new ServiceSearch(null,mapper.Object);
string accountNumber = "123";
string accountName = "";
// Act
var results = service.SearchAccount(accountNumber, accountName);
// Assert
Assert.IsTrue(results.Result.Count >= 1);
}
Method/Class That I'm Testing:
public class ServiceSearch : IServiceSearch
{
public ServiceSearch(IMapper<Claim, ClaimDTO> claimMapper, IMapper<Account, AccountDTO> accountMapper)
{
_claimMapper = claimMapper;
_accountMapper = accountMapper;
}
public async Task<List<AccountDTO>> SearchAccount(string accountNumber, string accountName)
{
var accounts = new List<Account>();
var accountDTOs = new List<AccountDTO>();
var results = await Task.Run(() => base.AccountSearch(accountNumber, accountName).Result);
if (results != null && results.Count > 0)
{
//Map DH to Domain
_accountMapper.Initialize();
foreach (AccountSearchResult result in results)
{
accounts.Add(_accountMapper.ToDomain(result));
}
//Map Domain to DTO
foreach (Account account in accounts)
{
accountDTOs.Add(_accountMapper.DomainToDto(account));
}
}
return accountDTOs;
}
}
This isn't the best place to use a Mock object because you are going to spend a lot of time writing your test objects and mock results. The issue with the setup call is that you haven't configured anything to send back in the result. A correct example would be:
// you would fully configure this object
AccountDTO expectedResult = new AccountDTO();
mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(expectedResult);
Now you can use the setup to configure different accountDTOs for different inputs.
You call also configure a callback to generate the account at test time:
mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns<AccountSearchResult>(sr => {
// build and return your dto here
});
However, unless your mapper is expensive to run or create, I think you'd better off just ensure that it is fully tested and acceptable and then use it to go ahead and generate the DTOs directly instead of trying to mock it out.
You don't actually setup an object in the ".Returns" call. You need to make sure to setup the ".Returns" to actually have an object with values.
Related
I have the following function that I am trying to put under unit test
public MessageListDto GetMessageList(SimpleSearchCriteria criteria)
{
var messages = _repository.GetMessages(criteria, out int total);
return new MessageListDto(messages, total);
}
and the following is my test so far, in which I am able to determine that _repository.GetMessages is call with the correct parameters.
However, how do I test that the second line is tested properly, I need to test that
A new object of type MessageListDto is constructed with the two parameters returned from the line above
the newly constructed object is returned
[Test]
public void Test1()
{
int total = 10;
var searchCriteria = new SimpleSearchCriteria();
var mockRepo = new Mock<IMessageRepository>();
var messageService = new MessageService(mockRepo.Object);
messageService.GetMessageList(searchCriteria);
mockRepo.Verify(r => r.GetMessages(searchCriteria, out total), Times.Once);
mockRepo.Verity ??????????
}
As we have discussed in the comment section your goal is to test the returned messages is passed to the dto's constructor without any modification.
With your current code you can't do that because you are creating the DTO explicitly inside your method. So, you can't replace it with a spy.
Just to clarify some terminologies:
Dummy: simple code that returns bogus data
Fake: a working alternative which can take shortcuts
Stub: custom logic with predefined data
Mock: custom logic with expectations (interactive stub)
Shim: custom logic at run-time
Spy: interceptors to record calls
To be able to capture the arguments of the MessageListDto constructor call you need to introduce an other layer between your GetMessageList method and the constructor. (In other words indirection)
For the sake of simplicity let me assume that IMessageRepository's GetMessages returns a string array.
So, you can introduce an interface like this:
public interface IDtoProvider
{
public MessageListDto CreateMessageList(string[] messages, int total)
=> new MessageListDto(messages, total);
}
Here I have used C# 8's interface default implementation feature
It can be further shortened with C# 9's target-typed new expression feature
If you are using older C# version then you need to separate the interface and the default implementation from each other
Now lets amend your MessageService to receive a IDtoProvider instance via its constructor
class MessageService
{
private readonly IMessageRepository _repository;
private readonly IDtoProvider _dtoProvider;
public MessageService(IMessageRepository repository, IDtoProvider dtoProvider)
=> (_repository, _dtoProvider) = (repository, dtoProvider);
public MessageListDto GetMessageList(SimpleSearchCriteria criteria)
{
var messages = _repository.GetMessages(criteria, out int total);
return _dtoProvider.CreateMessageList(messages, total);
}
...
}
Here I've took advantage of ValueTuple's deconstruct capability
With these in our hand we can write a unit test like this:
//Arrange - Repo
string[] messages = new[] { "OnlyElement" };
int total = 10;
var mockRepo = new Mock<IMessageRepository>();
mockRepo
.Setup(repo => repo.GetMessages(It.IsAny<SimpleSearchCriteria>(), out total))
.Returns(messages);
//Arrange - Provider
var dto = new MessageListDto(messages, total);
string[] messagesArgument = null;
int totalArgument = -1;
var mockProvider = new Mock<IDtoProvider>();
mockProvider
.Setup(provider => provider.CreateMessageList(It.IsAny<string[]>(), It.IsAny<int>()))
.Callback<string[], int>((messages, total) => (messagesArgument, totalArgument) = (messages, total))
.Returns(dto);
//Arrange - SUT
var searchCriteria = new SimpleSearchCriteria();
var sut = new MessageService(mockRepo.Object, mockProvider.Object);
//Act
sut.GetMessageList(searchCriteria);
//Assert - Repo
mockRepo.Verify(r => r.GetMessages(searchCriteria, out total), Times.Once);
//Assert - Provider
Assert.Equal(messages, messagesArgument);
Assert.Equal(total, totalArgument);
I've defined how should the IMessageRepository mock behave
I've defined how should the IDtoProvider mock behave
2.1 I've used here the Callback method to capture the calling argument
2.2 If you perform multiple calls against your mocked method then please consider to use Capture.In
I've instantiated a MessageService (which is our system under test) with the mock objects
I've called the GetMessageList inside the Act phase
I've made assertion against the repo mock call
I've made assertion against the calling parameters of the CreateMessageList
6.1 Here I have used xunit's assertion
The first step is to setup the MessageService mock, so that it returns something deterministic and then in the second step you verify that that has been used to construct your MessageListDto.
[Test]
public void Test1()
{
// arrange
int total = 10;
var searchCriteria = new SimpleSearchCriteria();
var messages = new [] {"message1", "message2"} // or similar
var mockRepo = new Mock<IMessageRepository>();
// or similar, I am not quite certain as to the specific syntax. Especially wrt. out parameters. Check the documentation.
mockRepo.Setup(x => x.GetMessages(It.IsAny<SimpleSearchCriteria>(), It.IsAny<int>())).Returns(messages);
var messageService = new MessageService(mockRepo.Object);
// act
var result = messageService.GetMessageList(searchCriteria);
// assert
mockRepo.Verify(r => r.GetMessages(searchCriteria, out total), Times.Once);
// or similar; here you might want to check out FluentAssertions as #Peter Csala suggested
Assert.Equal(result.Messages, messages);
}
What's missing from previous answers is that whenever possible, you should set up the mocked method with the exact parameters, that you expect it to receive. In other words set up the method with concrete values instead of It.IsAny<>(). In such case you won't have to verify the method later at all. (Unless it's critical to test, how many times a method is called). Simply, if mocked GetMessages receives different arguments than expected, it will return null, set total to 0 and your test will fail. Having the mocked methods set up properly, you can now focus on verifying what GetMessageList returns, which is the purpose of this unit test.
[Test]
public void Test1()
{
int total = 10;
var messages = new[] {new Message()};
var searchCriteria = new SimpleSearchCriteria();
var mockRepo = new Mock<IMessageRepository>();
mockRepo.Setup(_ => _.GetMessages(searchCriteria, out total))
.Returns(messages);
var messageService = new MessageService(mockRepo.Object);
var dto = messageService.GetMessageList(searchCriteria);
Assert.AreSame(messages, dto.Messages);
Assert.AreEqual(total, dto.Total);
}
I have a service that
Makes a call to each registered class that implements a specific interface (IUnorderedService)
Then makes a final call to another service (IFinalService)
I want to write a test that asserts that my service makes a call to each IUnorderedService in no specific order, and then makes a call to the IFinalService. Using FakeItEasy, is there any way to do this?
My implementation looks like this (much simplified):
public class MyService
{
private readonly IFinalService finalService;
private readonly IEnumerable<IUnorderedService> unorderedServices;
public MyService(
IFinalService finalService,
IEnumerable<IUnorderedService> unorderedServices)
{
this.finalService = finalService;
this.unorderedServices = unorderedServices;
}
public void Execute()
{
foreach (var unorderedService in this.unorderedServices)
{
unorderedService.Execute();
}
this.finalService.Execute();
}
}
And my test method would look something like this
public void ShouldCallUnorderedService_BeforeCallingFinalService()
{
// Arrange
...
// Act
myService.Execute();
// Assert
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly();
}
// Should be asserted that this call occurs after all of the above calls have occurred.
A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly();
}
I have played around with the A.CallTo().Then() syntax which works great for most purposes, but I don't see a way assert occurrence of multiple unordered calls prior to an ordered call.
There's nothing directly built into FakeItEasy for this scenario. One option would be to intercept the calls as they are made. Then you could verify the order was as you wanted. The call-intercepting feature is (I believe) infrequently used, so this might be less understandable, but could be worth pursuing.
Then I thought about leveraging the "callback" or Invokes facility on a Fake to record whether a fake call was supposed to be final or not, then verify the setting at the end of the test:
[Fact]
public void ShouldCallUnorderedService_BeforeCallingFinalService()
{
var lastKindOfService = "none";
var unorderedServices = new [] {
A.Fake<IUnorderedService>(),
A.Fake<IUnorderedService>(),
A.Fake<IUnorderedService>(),
};
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).Invokes(() => lastKindOfService = "unordered");
}
var finalService = A.Fake<IFinalService>();
A.CallTo(() => finalService.Execute()).Invokes(() => lastKindOfService = "final");
var service = new MyService(finalService, unorderedServices);
service.Execute();
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly();
}
A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly();
lastKindOfService.Should().Be("final");
}
Of course this could be prettied up with a helper method or enums for the state. And if there's any asynchrony, you might want to serialize the updates.
You can put the A.CallTo().Then() into your foreach
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly()
.Then(A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly()
}
So you are checking that each call to the unordered service happened before the call to the final service. Unfortunately this is not a bulk check, but I think the end result will still prove code correctness
I have a basic .NET application that I am being asked to write a unit test for, but unit tests have always confused me.
This application has two repositories (FoodRepository and DrinkRepository) that return data from a hardcoded list.
Here's the Program.cs:
public static void Main(string[] args)
{
var foodSvc = new FoodService();
var foodId = 12;
var grade = 98.2d;
foodSvc.UpdateFoodGrade(foodId, grade);
}
which calls:
public void UpdateFoodGrade(int foodId, double grade)
{
var foodRepo = new FoodRepository();
var food = foodRepo.GetFood(foodId);
food.Grade = grade;
if (!food.IsPassed)
{
var drinkRepository = new DrinkRepository();
var drink = drinkRepository.GetDrink(foodId);
if (grade >= drink.MinimumPassingGrade)
{
food.IsPassed = true;
}
else
{
food.IsPassed = false;
}
}
}
My question is, what unit test(s) typically would someone do here for this? And, can I get some examples?
Been googling and grinding on this, but the concept continues to escape me.
I've historically used full integration tests in test environments, and not really done unit tests.
If anyone needs more of the code to help with this please let me know. I'm super stuck.
Thanks
UPDATE:
I've gotten a lot further thanks to below, but I am still stuck on the rest of the test. Here's what my updated service looks like:
public class FoodService
{
private readonly FoodRepository _foodRepo;
private readonly DrinkRepository _drinkRepository;
public FoodService(FoodRepository foodRepo, DrinkRepository drinkRepository)
{
_foodRepo = foodRepo;
_drinkRepository = drinkRepository;
}
public void UpdateFoodGrade(int foodId, double grade)
{
var food = _foodRepo.GetFood(foodId);
food.Grade = grade;
if (!food.IsPassed)
{
var drink = _drinkRepository.GetDrink(foodId);
if (grade >= drink.MinimumPassingGrade)
{
food.IsPassed = true;
}
else
{
food.IsPassed = false;
}
}
}
}
Updated Main:
public class Program
{
public static void Main(string[] args)
{
var foodRepository = new FoodRepository();
var drinkRepository = new DrinkRepository();
var foodSvc = new FoodService(foodRepository, drinkRepository);
var foodId = 12;
var grade = 98.2d;
foodSvc.UpdateFoodGrade(foodId, grade);
}
}
Test So far (I have no idea what to do next)
[TestMethod]
public void UpdateFoodGrade_Test()
{
//Arrange
var foodId = 12;
var grade = 98.2d;
var expected = true;
var food = new Food() { FoodId = foodId };
var drink = new Drink() { DrinkId = foodId };
var foodRepositoryMock = new Mock<FoodRepository>();
foodRepositoryMock.Setup(m => m.GetFood(foodId)).Returns(food).Verifiable();
var drinkRepositoryMock = new Mock<DrinkRepository>();
drinkRepositoryMock.Setup(m => m.GetDrink(foodId)).Returns(drink).Verifiable();
var foodService = new FoodService(foodRepositoryMock.Object, drinkRepositoryMock.Object);
//Act
var actual = foodService.UpdateFoodGrade(foodId, grade);
//Assert
foodRepositoryMock.Verify();
drinkRepositoryMock.Verify();
Assert.AreEqual(expected, actual);
}
}
EDIT 2:
I went ahead and refactored in the interfaces, etc. Here's how it shook out:
[TestMethod]
public void UpdateLessonGrade_IsPassingGrade()
{
//Arrange
var lessonId = 12;
var lesson = new Lesson() { LessonId = lessonId };
var module = new Module() { ModuleId = lessonId };
var lessonRepositoryMock = new Mock<ILessonRepository>();
lessonRepositoryMock.Setup(x => x.GetLesson(lessonId)).Returns(lesson);
var moduleRepositoryMock = new Mock<IModuleRepository>();
moduleRepositoryMock.Setup(x => x.GetModule(lessonId)).Returns(module);
var lessonService = new LessonService(lessonRepositoryMock.Object, moduleRepositoryMock.Object);
//Act
lessonService.UpdateLessonGrade(12, 98.2d);
//Assert
Assert.IsTrue(lesson.IsPassed); // assuming it should pass in this condition
Assert.AreEqual(98.2d, lesson.Grade); // expected Lesson Grade should be what you expected the grade to be after you call UpdateLessonGrade
}
I'm on a mobile device right now, I can try to update the answer later this weekend, but this should get you started.
Refactor your method to use instance variables instead of direct instantiation in the method. Add them as parameters to your constructor. In the main method create your repository instances and pass them to the service constructor.
Now you can use something like Moq or the in memory provider for entity framework.
As for what to test, basically test every piece of branching logic. At a minimum, each piece of an if statement and the else conditions. You should also test what happens when your repository objects don't find what you're looking for (e.g. returns null). Offhand, I'm counting at least six tests.
Update: Bravo! Looking at your updated code in the question, everything is on the right track.
In your test method, you'll want to add:
var foodService = new FoodService(foodRepositoryMock.Object, drinkRepositoryMock.Object);
That will initialize your service with the mock objects.
Then you'll want to call your service with test parameters like:
foodService.UpdateFoodGrade(12, 98.2d);
The last part is check your food object using asserts like:
Assert.IsTrue(food.IsPassed) // assuming it should pass in this condition
Assert.Equals(98.2d, food.Grade); // expectedFoodGrade should be what you expected the grade to be after you call UpdateFoodGrade
It looks like you'll also need to flesh out the instance of your Drink object a little bit more. You need to specify a value for MinimumPassingGrade since it's used to drive the decision logic in your if statement, for example, if you want the food.IsPassed = true to trigger, you would instantiate the drink object like so:
var drink = new Drink() { DrinkId = foodId, MinimumPassingGrade = 50.0d };
You would create test methods for each of the other various test cases, failed the minimum, when it's equal to the score, if you can't find the food in the food repo, or the drink in the drink repo, etc.
One other note, you only need to worry about Verifiable mocks when you need to know that a method was/wasn't called. For these tests, I probably wouldn't verify that methods were called (creates tighter coupling between your test and the implementation vs. the behavior). You'd want to verify that the methods were called only if something in your service code truly depends on knowing that it was called. e.g. if you're using Entity Framework and you wanted to make sure you didn't forget to call SaveChanges().
Indeed, such code can't be "normally" unit-tested without preliminary refactoring. But you still have one (bit dirty) option: Shims mechanism of MS Fakes Library.
It allows you to substitute any method or property of any type (including static, non-public and system) with any arbitrary code. In your case you may create a ShimsContext in you test method, and give some fake behavior for FoodRepository.GetFood() and DrinkRepository.GetDrink() methods, for example, empty body doing nothing. So, when your test runs, your stub code gonna be executed instead of the actual code of repository classes. So you will test only Service code without executing code of repositories.
You may check this article for quick introduction to the library.
And please keep in mind that Shims is not a way of good unit-testing, It is just a tool to deal with such non-testable code in case when you absolutely need to unit-test it somehow without changing the code itself.
I have build a WebAPI and want to create a unit test project to have my services tested automatically.
The flow of my WebAPI is simple:
Controller (DI Service) -> Service (DI Repository) -> _repo CRUD
Suppose I have a service like:
public int Cancel(string id) //change status filed to 'n'
{
var item = _repo.Find(id);
item.status = "n";
_repo.Update(item);
return _repo.SaveChanges();
}
And I want to build a unit test, which just use InMemoryDatabase.
public void Cancel_StatusShouldBeN() //Testing Cancel() method of a service
{
_service.Insert(item);
int rs = _service.Cancel(item.Id);
Assert.Equal(1, rs);
item = _service.GetByid(item.Id);
Assert.Equal("n", item.status);
}
I've searched other related question, found that
You can't use dependency injections on test classes.
I just want to know if there is any other solution to achive my unit test idea?
When unit testing, you should just supply all the dependencies of the class you are testing explicitly. That is dependency injection; not having the service construct its dependencies on its own but making it rely on the outer component to provide them. When you are outside of a dependency injection container and inside a unit test where you are manually creating the class you are testing, it’s your responsibility to provide the dependencies.
In practice, this means that you either provide mocks or actual objects to the constructor. For example, you might want to provide a real logger but without a target, a real database context with a connected in-memory database, or some mocked service.
Let’s assume for this example, that the service you are testing looks like this:
public class ExampleService
{
public ExampleService(ILogger<ExampleService> logger,
MyDbContext databaseContext,
UtilityService utilityService)
{
// …
}
// …
}
So in order to test ExampleService, we need to provide those three objects. In this case, we will do the following for each:
ILogger<ExampleService> – we will use a real logger, without any attached target. So any call on the logger will work properly without us having to provide some mock, but we do not need to test the log output, so we do not need a real target
MyDbContext – Here, we’ll use the real database context with an attached in-memory database
UtilityService – For this, we will create a mock which just setups the utility method we need inside the methods we want to test.
So a unit test could look like this:
[Fact]
public async Task TestExampleMethod()
{
var logger = new LoggerFactory().CreateLogger<ExampleService>();
var dbOptionsBuilder = new DbContextOptionsBuilder().UseInMemoryDatabase();
// using Moq as the mocking library
var utilityServiceMock = new Mock<UtilityService>();
utilityServiceMock.Setup(u => u.GetRandomNumber()).Returns(4);
// arrange
using (var db = new MyDbContext(dbOptionsBuilder.Options))
{
// fix up some data
db.Set<Customer>().Add(new Customer()
{
Id = 2,
Name = "Foo bar"
});
await db.SaveChangesAsync();
}
using (var db = new MyDbContext(dbOptionsBuilder.Options))
{
// create the service
var service = new ExampleService(logger, db, utilityServiceMock.Object);
// act
var result = service.DoSomethingWithCustomer(2);
// assert
Assert.NotNull(result);
Assert.Equal(2, result.CustomerId);
Assert.Equal("Foo bar", result.CustomerName);
Assert.Equal(4, result.SomeRandomNumber);
}
}
In your specific Cancel case, you want to avoid using any methods of the service you are not currently testing. So if you want to test Cancel, the only method you should call from your service is Cancel. A test could look like this (just guessing the dependencies here):
[Fact]
public async Task Cancel_StatusShouldBeN()
{
var logger = new LoggerFactory().CreateLogger<ExampleService>();
var dbOptionsBuilder = new DbContextOptionsBuilder().UseInMemoryDatabase();
// arrange
using (var db = new MyDbContext(dbOptionsBuilder.Options))
{
// fix up some data
db.Set<SomeItem>().Add(new SomeItem()
{
Id = 5,
Status = "Not N"
});
await db.SaveChangesAsync();
}
using (var db = new MyDbContext(dbOptionsBuilder.Options))
{
// create the service
var service = new YourService(logger, db);
// act
var result = service.Cancel(5);
// assert
Assert.Equal(1, result);
}
using (var db = new MyDbContext(dbOptionsBuilder.Options))
{
var item = db.Set<SomeItem>().Find(5);
Assert.Equal(5, item.Id);
Assert.Equal("n", item.Status);
}
}
Btw. note that I’m opening up a new database context all the time in order to avoid getting results from the cached entities. By opening a new context, I can verify that the changes actually made it into the database completely.
I am new to simple injector. I have data access layer that has dependency on Force Client. I have register the ForceClient dependency. I want to replace the default value of ForceClient once user login into the application.
Please let me know, how i can change the default values at run time.
Ioc.ServiceContainer.Register(() => new ForceClient(
"test",
"test",
"test"));
Here is the complete detail about the requirement. I have DAL in our Xamarin project that retrieve data from sales force using Developerforce.Force apis. I am writing unit test cases using MOQ to test the DAL.
DAL Code.
public CustomerRepository(IForceClient client)
{
_client = client;
}
public async Task<long> GetTotalContacts()
{
string totalContactCountQry = "some query"
var customerCount = await _client.QueryAsync<ContactsTotal>(totalContactCountQry);
var firstOrDefault = customerCount.Records.FirstOrDefault();
return firstOrDefault != null ? firstOrDefault.Total : 0;
}
Unit Test Case Code.
[SetUp]
public void Init()
{
forceClientMock = new Mock<IForceClient>();
forceClientMock.Setup(x => x.ForceClient(It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<HttpClient>()))
.Return(new ForceClient(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<HttpClient>()));
forceClientMock.Setup(x => x.QueryAsync<ContactsTotal>(It.IsAny<string>()))
.ReturnsAsync(new QueryResult<ContactsTotal>());
forceClientMock.Setup(x => x.QueryAsync<ContactsTotal>(It.IsAny<string>()))
.ReturnsAsync(new QueryResult<ContactsTotal>() { Records=new List<ContactsTotal>() });
}
[Test]
public void GetTotalContacts()
{
ICustomerRepository customerRepostory = new CustomerRepository(forceClientMock.Object);
Assert.AreEqual(customerRepostory.GetTotalContacts().Result,0);
}
Simple Injector Registry on application initialization
container.Register<IForceClient>((() => new ForceClient(
UserState.Current.ApiBaseUrl,
UserState.Current.AuthToken.AccessToken,
UserState.Current.ApiVersion)), Lifestyle.Transient);
The instance of ForceClient that i am creating during the registry is being created with all default valued of UserState. The actual value gets assigned once user login into the application.
I except ForceClient instance to have the updated value after login to access the sales force to retrieve the data but the program is giving error on below line DAL
var customerCount = await _client.QueryAsync<ContactsTotal>(totalContactCountQry);
The reason is that the forceClient still contain default values. How can i make sure that the FoceClient instance get created after login to use the actual value of UserState
You can accomplish what you want by using Func<T>.
Rather than IForceClient in your classe, you can inject a Func<IForceClient> :
public CustomerRepository(Func<IForceClient> clientFunc)
{
_clientFunc = clientFunc;
}
public async Task<long> GetTotalContacts()
{
string totalContactCountQry = "some query"
// calling _clientFunc() will provide you a new instance of IForceClient
var customerCount = await _clientFunc().QueryAsync<ContactsTotal>(totalContactCountQry);
var firstOrDefault = customerCount.Records.FirstOrDefault();
return firstOrDefault != null ? firstOrDefault.Total : 0;
}
The simple injector registration:
// Your function
Func<IForceClient> fonceClientFunc = () => new ForceClient(
UserState.Current.ApiBaseUrl,
UserState.Current.AuthToken.AccessToken,
UserState.Current.ApiVersion);
// the registration
container.Register<Func<IForceClient>>( () => fonceClientFunc, Lifestyle.Transient);