adding records to inmemorydatabase just once - c#

I am trying to write my very first xunit test with Database, instead of mocking the DbContext I used the inMemoryDatabase as I read in articles, so I did like following
public class GetCustomersTest
{
DbContextOptions _context;
public GetCustomersTest()
{
if (_context==null)
_context = CreateContextForCustomer();
}
[Theory]
[InlineData(1)]
[InlineData(2)]
public void GetCustomerById_ShouldReturnCorrectObject(int id)
{
using (var context = new DataBaseContext(_context))
{
var customerByIdService = new GetCustomerByIdService(context);
var customer = customerByIdService.Execute(id);
var customerActual = context.Customers.Where(x => x.Id == id).SingleOrDefault();
var customerTmp = new Customer()
{
Id = id,
FirstName = customer.Data.FirstName,
LastName = customer.Data.LastName,
Phone = customer.Data.Phone,
ClientNote = customer.Data.ClientNote
};
Assert.Equal(customerTmp.FirstName, customerActual.FirstName);
Assert.Equal(customerTmp.LastName, customerActual.LastName);
Assert.Equal(customerTmp.Phone, customerActual.Phone);
Assert.Equal(customerTmp.ClientNote, customerActual.ClientNote);
}
}
private DbContextOptions<DataBaseContext> CreateContextForCustomer() {
var options = new DbContextOptionsBuilder<DataBaseContext>()
.UseInMemoryDatabase(databaseName: "SalonDatabase")
.Options;
using (var context = new DataBaseContext(options))
{
context.Customers.Add(new Customer
{
Id = 1,
FirstName = "User1",
LastName = "Surname1",
Phone = "123",
ClientNote = ""
});
context.Customers.Add(new Customer
{
Id = 2,
FirstName = "User2",
LastName = "Surname2",
Phone = "4567",
ClientNote = "The best"
});
context.SaveChanges();
}
return options;
}
}
it works find on [InlineData(1)] but when it comes to [InlineData(2)], it seems that it starts to run the constructor again , so as it wants to add the customerdata to table, it says that the record with that Id key exists.what is the best way for doing that?

When building your DB context options, add a GUID to the database name to make it unique:
var options = new DbContextOptionsBuilder<DataBaseContext>()
.UseInMemoryDatabase(databaseName: "SalonDatabase" + Guid.NewGuid().ToString())
.Options;
Or if you're using a new enough language version you can use string interpolation instead of concatenation:
var options = new DbContextOptionsBuilder<DataBaseContext>()
.UseInMemoryDatabase(databaseName: $"SalonDatabase{Guid.NewGuid()}")
.Options;
If you do this then every test uses a brand new database, unaffected by any previous tests.
As #MicheleMassari says, it's good practice to follow the Arrange Act Assert pattern, so that it's clear which lines are setting things up ready for the test and which are performing the action that you want to test the outcome of.
Arrange inputs and targets. Arrange steps should set up the test case. Does the test require any objects or special settings? Does it need to prep a database? Does it need to log into a web app? Handle all of these operations at the start of the test.
Act on the target behavior. Act steps should cover the main thing to be tested. This could be calling a function or method, calling a REST API, or interacting with a web page. Keep actions focused on the target behavior.
Assert expected outcomes. Act steps should elicit some sort of response. Assert steps verify the goodness or badness of that response. Sometimes, assertions are as simple as checking numeric or string values. Other times, they may require checking multiple facets of a system. Assertions will ultimately determine if the test passes or fails.
The code samples in that page are written in Python rather than C#, but the pattern is valid for unit tests in any language. In the case of your test, structuring the test in this way makes it clear whether you're testing the behaviour of GetCustomerByIdService.Execute or of Entity Framework's Where method.

Related

Fake Xrm Easy: How to emulate a plugin's behaviour on orgService.Create()?

Microsoft Dynamics CRM 2015.
I test Asp.Net Core controller's action. When I create new Lead record some plugin generates new Guid for lead.new_master_id field (it's type is string). Therefore after creating I retrive the record to get it's generated new_master_id value. How can I emulate this plugin behaviour through Fake Xrm Easy?
var fakedContext = new XrmFakedContext();
fakedContext.ProxyTypesAssembly = typeof(Lead).Assembly;
var entities = new Entity[]
{
// is empty array
};
fakedContext.Initialize(entities);
var orgService = fakedContext.GetOrganizationService();
var lead = new Lead { FirstName = "James", LastName = "Bond" };
var leadId = orgService.Create(lead);
var masterId = orgService.Retrieve(Lead.EntityLogicalName, leadId,
new Microsoft.Xrm.Sdk.Query.ColumnSet(Lead.Fields.new_master_id))
.ToEntity<Lead>().new_master_id;
In v1.x of FakeXrmEasy you'll need to enable PipelineSimulation and register the plugin steps you would like to be fired on Create manually by registering their steps.
fakedContext.UsePipelineSimulation = true;
Once enabled, you'll need to enable the necessary steps via calling RegisterPluginStep. In your example you'll need to at least register something along the lines of:
fakedContext.RegisterPluginStep<LeadPlugin>("Create", ProcessingStepStage.Preoperation);
Where LeadPlugin would be the name of your plugin that generates the new_master_id property.
Keep in mind v1.x is limited in that it supports pipeline simulation for basic CRUD requests only.
Later versions (2.x and/or 3.x) come with a brand new middleware implementation allowing registering plugin steps for any message. Soon we'll be implementing automatic registration of plugin steps based on an actual environment and/or custom attributes.
Here's an example using the new middleware
public class FakeXrmEasyTestsBase
{
protected readonly IXrmFakedContext _context;
protected readonly IOrganizationServiceAsync2 _service;
public FakeXrmEasyTestsBase()
{
_context = MiddlewareBuilder
.New()
.AddCrud()
.AddFakeMessageExecutors()
.AddPipelineSimulation()
.UsePipelineSimulation()
.UseCrud()
.UseMessages()
.Build();
_service = _context.GetAsyncOrganizationService2();
}
}
You can find more info on the QuickStart guide here
Disclaimer: I'm the author of FakeXrmEasy :)

Ways to test SearchResults<T> Class in Azure.Search.Documents v11.2.0

I'm trying to find out a way to unit test the search results from the SearchResults<T> Class with different parameters.
Compared to DocumentSearchResult<T> Class which was in the previous package Microsoft.Azure.Search.Data v10.1.0, SearchResults<T> Class does not have any constructors, just properties and methods.
DocumentSearchResult<T> Class
https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.search.models.documentsearchresult-1?view=azure-dotnet
SearchResults<T> Class
https://learn.microsoft.com/en-us/dotnet/api/azure.search.documents.models.searchresults-1?view=azure-dotnet
I couldn't seem to find any documentation on that online as it is relatively new, but any ideas or suggestions are most welcome.
Thank you.
All our Azure SDKs for .NET matching package names Azure.* like Azure.Search.Documents are mockable using the same principles as shown here. For pure response objects like SearchResults<T>, we create model factories so that you can create them for testing. In general, there is no other intended purpose for creating them apart from testing.
Using Moq, for example:
// Arrange
var mockResponse = new Mock<Response>();
var mockResults = SearchModelFactory.SearchResults<Model>(new[]
{
SearchModelFactory.SearchResult<Model>(new Model { Name = "a" }, 1.0),
SearchModelFactory.SearchResult<Model>(new Model { Name = "b" }, 0.9),
}, 2, rawResponse: response.Object);
var mockClient = new Mock<SearchClient>();
mockClient.Setup(m => m.Search<Model>(It.IsAny<string>(), It.IsAny<SearchOptions>(), default))
.Returns(Response.FromValue(mockResults, mockResponse.Object));
// Act
var response = mockClient.Object.Search<Model>("anything");
// Assert
Assert.AreEqual(2, response.Value.TotalCount);
See more mocking samples for other ideas.
The SearchModelFactory is the class that will help you to create the models for SearchResults.
This reading can also be helpful for another kind of tests: https://devblogs.microsoft.com/azure-sdk/unit-testing-and-mocking/
Just in case someone else is looking for a version using NSubstitute, here is mine:
public async Task TheTest()
{
// Arrange
var searchResultValues = new List<SearchResult<MyModel>>
{
SearchModelFactory.SearchResult<MyModel>(new MyModel{Id = 1}, score:0.9, highlights:null),
SearchModelFactory.SearchResult<MyModel>(new MyModel{Id = 2}, score:0.8, highlights:null),
};
var searchResults = SearchModelFactory.SearchResults<MyModel>(searchResultValues, totalCount: 2, facets: null, coverage: 1.3, rawResponse: Substitute.For<Response>());
var response = Response.FromValue(searchResults, Substitute.For<Response>());
var searchClient = Substitute.For<SearchClient>();
searchClient.SearchAsync<MyModel>(Arg.Any<string>(), Arg.Any<SearchOptions>()).Returns(Task.FromResult(response));
var sut = new ClassThatUsesTheSearchClient(searchClient);
// Act
var result = await sut.MethodToSearch();
// or directly
var directResult = await searchClient.SearchAsync<MyModel>("text");
// Assert
Assert.AreEqual(2, directResult.Value.TotalCount);
...
}

EF Core : Testing with InMemory Database has inconsistent behavior

I'm using the InMemory database to test my repository layer in my ASP .NET Core Web API application.
Thus I have an issue, in several tests, I setup data. But, with the same code, when I run the tests sometimes the data is present and sometimes it is not. I don't understand why.
I'm using XUnit Testing Framework.
Here is my test :
public class UserRepositoryTest
{
private ApplicationDbContext context;
void setup()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "ApplicationDatabase")
.Options;
this.context = new ApplicationDbContext(options);
this.context.Database.EnsureDeleted();
}
[Fact]
void GetUserByUsernameTest()
{
this.setup();
// Given
var manager = new User {Username = "Ombrelin", Email = "test#test.fr"};
context.Users.Add(manager);
context.SaveChanges();
// When
var repo = new UserRepository(context);
var user = repo.GetUserByUsername("Ombrelin");
// Then
Assert.Equal("Ombrelin", user.Username);
}
[Fact]
void FindUsersByUsernameContainsTest()
{
this.setup();
// Given
var manager1 = new User {Username = "Arsène", Email = "test#test.fr"};
var manager2 = new User {Username = "Jean Michel", Email = "test#test.fr"};
context.Users.Add(manager1);
context.Users.Add(manager2);
context.SaveChanges();
// When
var repo = new UserRepository(context);
var users = repo.findUsersByUsernameContains("Ars");
// Then
Assert.Single(users);
}
Does anyone have a clue about this ?
Thanks in advance,
You are reusing the same database context across multiple tests. Tests may run in parallel. Thus, when using the same database context tests may influence each other's outcome. To avoid this, you need to isolate the tests by letting them use a clean database context:
public class UserRepositoryTest
{
[Fact]
public void GetUserByUsernameTest()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: $"ApplicationDatabase{Guid.NewGuid()}")
.Options;
using(var context = new ApplicationDbContext(options))
{
// Given
var manager = new User { Username = "Ombrelin", Email = "test#test.fr" };
context.Users.Add(manager);
context.SaveChanges();
// When
var repo = new UserRepository(context);
var user = repo.GetUserByUsername("Ombrelin");
// Then
Assert.Equal("Ombrelin", user.Username);
}
}
}
By appending a unique id to the database name, you are ensuring, that tests are using a unique in-memory database. Obviously, this will make test execution slower. A lot of testers also use different contexts for seeding the data and performing the test:
public class UserRepositoryTest
{
[Fact]
public void GetUserByUsernameTestSeparateContexts()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: $"ApplicationDatabase{Guid.NewGuid()}")
.Options;
using (var context = new ApplicationDbContext(options))
{
// Given
var manager = new User { Username = "Ombrelin", Email = "test#test.fr" };
context.Users.Add(manager);
context.SaveChanges();
}
using (var context = new ApplicationDbContext(options))
{
// When
var repo = new UserRepository(context);
var user = repo.GetUserByUsername("Ombrelin");
// Then
Assert.Equal("Ombrelin", user.Username);
}
}
}
This makes the tests more realistic, since functions, that are seeding the data, and functions, that are using the data, often use different contexts. Also keep in mind, that the InMemoryProvider is not a relational database. Therefore, it does not support some features of actual database servers such as referential integrity checks, TimeStamp, IsRowVersion and others. Check the MS documentation for details: here.

MVC4 Unit test NSubstitute Could not find a call to return from

I have a MVC4 web application I'm unit testing right now. It uses entity framework for the database portion. I'm using NSubstitute to mock the database. This code is basically copied and pasted from another site which works fine, so I hope I'm just missing something super simple.
Thanks in advance!
Applications table in SQL:
AppID | ApplicationName
----------------------------
1 | MyCoolApplication
2 | MyOtherApplication
Entity created the Application class:
public class Application
{
public int AppID { get; set; }
public string ApplicationName { get; set; }
}
The mock section of the unit test looks like this:
var mockDb = Substitute.For<MyCoolApplicationsEntities>();
var applications = new List<Application>
{
new Application {AppID = 1, ApplicationName = "MyCoolApplication"},
new Application {AppID = 2, ApplicationName = "MyOtherApplication"},
};
var mockApplicationSet = Substitute.For<IDbSet<Application>, DbSet<Application>>();
mockApplicationSet.Provider.Returns(applications.AsQueryable().Provider);
mockApplicationSet.Expression.Returns(applications.AsQueryable().Expression);
mockApplicationSet.ElementType.Returns(applications.AsQueryable().ElementType);
mockApplicationSet.GetEnumerator().Returns(applications.AsQueryable().GetEnumerator());
mockApplicationSet.When(q => q.Add(Arg.Any<Application>()))
.Do(q => applications.Add(q.Arg<Application>()));
mockApplicationSet.When(q => q.Remove(Arg.Any<Application>()))
.Do(q => applications.Remove(q.Arg<Application>()));
mockDb.Applications.Returns(mockApplicationSet); //This is the line creating the error
The full error is:
Test method
MyProjectName.Controllers.MyControllerTest.TestOfSectionImTesting
threw exception:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException:
Could not find a call to return from.
Make sure you called Returns() after calling your substitute (for
example: mySub.SomeMethod().Returns(value)), and that you are not
configuring other substitutes within Returns() (for example, avoid
this: mySub.SomeMethod().Returns(ConfigOtherSub())).
If you substituted for a class rather than an interface, check that
the call to your substitute was on a virtual/abstract member. Return
values cannot be configured for non-virtual/non-abstract members.
Correct use:
mySub.SomeMethod().Returns(returnValue);
Potentially problematic use:
mySub.SomeMethod().Returns(ConfigOtherSub());
Instead try:
var returnValue = ConfigOtherSub();
mySub.SomeMethod().Returns(returnValue);
But that doesn't work in my environment because Applications isn't a method. Like I said, this works fine in another site of mine, so it's got to be something basic I'm missing. Nothing I've found online has been helpful with my particular case. I updated to the newest version of NSubstitute and I uninstalled/reinstalled, but still have got nothing.
Again, thanks in advance!
NSubstitute can not mock non-virtual members. (There are quite a few caveats to substituting for classes.)
MyCoolApplicationsEntities.Applications will need to be virtual for .Returns() to work.
Here's what ended up working:
var context = Substitute.For<MyCoolApplicationsEntities>();
var applications = new List<Application>
{
new Application {AppID = 1, ApplicationName = "MyCoolApplication"}
};
var mockApplications = Substitute.For<DbSet<Application>, IQueryable<Application>>();
((IQueryable<Application>)mockApplications).Provider.Returns(applications.AsQueryable().Provider);
((IQueryable<Application>)mockApplications).Expression.Returns(applications.AsQueryable().Expression);
((IQueryable<Application>)mockApplications).ElementType.Returns(applications.AsQueryable().ElementType);
((IQueryable<Application>)mockApplications).GetEnumerator().Returns(applications.AsQueryable().GetEnumerator());
mockApplications.When(q => q.Add(Arg.Any<Application>()))
.Do(q => applications.Add(q.Arg<Application>()));
mockApplications.When(q => q.Remove(Arg.Any<Application>()))
.Do(q => applications.Remove(q.Arg<Application>()));
context.Applications = mockApplications;
I can't see you classes but you need to create interfaces with virtual members and have your code call the class by the interface, then you will be able to mock out the class.

How to write a Unit Test in CRM 2011 development

I am willing to start writing Unit Tests for my CRM 2011 code. I have very little experience of Unit Testing, so I would like some help with it.
The method I would like to test is:
public Proxy.custom_serviceobject PopulateServiceObject(Proxy.custom_serviceobject crmServiceObject, serviceobject irisServiceObject, Guid locationId)
{
//set the reference to the location the order is connected to
crmServiceObject.custom_location = new EntityReference("custom_location", locationId);
//add the reference to the product in the serviceobject
crmServiceObject.custom_product = new EntityReference("product", new Guid(irisServiceObject.ItemId));
//convert the errorid to an int
Int32 errorId;
var success = Int32.TryParse(irisServiceObject.ErrorId, out errorId);
crmServiceObject.custom_errorclassOptionSetValue = success ? new OptionSetValue(errorId) : new OptionSetValue(Int32.MinValue);
crmServiceObject.custom_serviceobjecttype =
new EntityReference("custom_serviceobjecttype", new Guid(irisServiceObject.ObjectType.Id));
crmServiceObject.custom_placement = irisServiceObject.SortId;
crmServiceObject.custom_yearofinstallationOptionSetValue = new OptionSetValue(irisServiceObject.AuditYear);
crmServiceObject.custom_yearofmanufactureOptionSetValue = new OptionSetValue(irisServiceObject.ProductionYear);
crmServiceObject.custom_location = new EntityReference("custom_location", new Guid(irisServiceObject.Location));
crmServiceObject.custom_quantity = irisServiceObject.Qty;
crmServiceObject.custom_remark = irisServiceObject.ExternalNote;
crmServiceObject.custom_internalremark = irisServiceObject.InternalNote;
if (irisServiceObject.Cancelled)
{
var setStateRequest = new SetStateRequest
{
EntityMoniker = new EntityReference
{
Id = crmServiceObject.Id,
LogicalName = "custom_serviceobject"
},
State = new OptionSetValue(StatusInactive),
Status = new OptionSetValue(StatusReasonInactive)
};
Service.Execute(setStateRequest);
}
return crmServiceObject;
}
Do you have some ideas about what kind of test I could write? Should I mock some components?
Your method only does two things, update some values in the crmServiceObject, and execute an update statement. Since there is nothing CRM specific (besides besides the crmServiceObject being a type defined by CRM) to unit testing updating an object I'll skip that part of it.
As far as the CRM call to disable the entity, you've got two options for a unit test. Verify that CRM performed a disable or not, or mock an IOrganizationService and assert that the Execute call was made or not. It's up to you really.
This question may be helpful as well, although it relates to plugins specifically.

Categories

Resources