I am using the Moq framework for my unit test.
This is my TestMethod:
[TestFixture]
public class UpdateContactTests
{
private static readonly object[] TestValidContact =
{
new object[]
{
"Prueba", "nearlinx#gmail.com", "86456245",
new LookUpItem()
{
LookUpItemId = Guid.NewGuid(), Category = "ContactType", CategoryId = 1, Value = "Bulling Contact"
},
new Company()
{
Id = Guid.NewGuid(), Name = "Company", Email = "company#gmail.com", WebSite = "company.com",
Nda = false, Msa = false, Phone = "84876817"
}
}
};
[TestCaseSource(nameof(TestValidContact))]
[Test]
public void UpdateContact_ValidValues_UpdateContact(string name, string email, string phone, LookUpItem lookUpItem, Company company)
{
//arrange
var id = Guid.NewGuid();
var data =
new[]
{
new Contact { Id = Guid.NewGuid(), Name = "Test1", Email = "nearlinx#gmail.com", Phone = "86456245",
ContactType =
new LookUpItem()
{
LookUpItemId = Guid.NewGuid(), Category = "ContactType", CategoryId = 1, Value = "Bulling Contact"
},
Company =
new Company()
{
Id = Guid.NewGuid(), Name = "Company", Email = "company#gmail.com", WebSite = "company.com",
Nda = false, Msa = false, Phone = "84876817"
}},
new Contact { Id = id, Name = "Test2", Email = "nearlinx#gmail.com", Phone = "86456245",
ContactType =
new LookUpItem()
{
LookUpItemId = Guid.NewGuid(), Category = "ContactType", CategoryId = 1, Value = "Bulling Contact"
},
Company =
new Company()
{
Id = Guid.NewGuid(), Name = "Company", Email = "company#gmail.com", WebSite = "company.com",
Nda = false, Msa = false, Phone = "84876817"
}},
};
var contact = new Contact()
{
Id = id,
Name = name,
Email = email,
Phone = phone,
ContactType = lookUpItem,
Company = company
};
var _unitOfWork = new Mock<IUnitOfWork>();
_unitOfWork.Setup(mock => mock.Contact.Get(null, null, null)).Returns(data);
_unitOfWork.Setup(mock => mock.Company.Get(null, null, null)).Returns(new List<Company>());
_unitOfWork.Setup(mock => mock.LookUpItem.Get(null, null, null)).Returns(new List<LookUpItem>());
var contactService = new ContactService(_unitOfWork.Object);
//act
contactService.UpdateContact(contact);
//assert
Assert.That(data.First(m => m.Id == id).Name, Is.EqualTo(contact.Name));
_unitOfWork.Verify(mock => mock.Contact.Update(It.IsAny<Contact>()), Times.Once);
}
}
My problem is that when I run the test a NullReferenceException is thrown, I suppose it is because the list that has the object that I want to modify is not being assigned
I've never really used Moq and I don't know much about unit tests either, so what am I really doing wrong
Edit:
i change one of the setup because the one called when the update is done was another
instead of
_unitOfWork.Setup(mock => mock.Contact.Get(null, null, null)).Returns(data);
is
_unitOfWork.Setup(mock => mock.Contact.Where(c => c.Id == contact.Id,null,null).FirstOrDefault()).Returns(() => data.Where(c => c.Id == contact.Id));
Without seeing the rest
_unitOfWork.Setup(mock => mock.Contact.Get(null, null, null))
the mock.Contact returns null
best thing is to debug the test, breakpoint the first line and step through to find exactly where it is throwing the null exception
I found the solution
I was doing the set like this
_unitOfWork.Setup(mock => mock.Contact.Where(c => c.Id == contact.Id,null,null).FirstOrDefault()).Returns(() => data.Where(c => c.Id == contact.Id));
while in the update method the condition was this
_unitOfWork.Setup(mock => mock.Contact.Where(c => c.Id == contact.Id).FirstOrDefault()).Returns(() => data.Where(c => c.Id == contact.Id));
changing the condition in the method fixed the problem
Related
I'm searching on multiple columns I want to determine which column matched my search text on the results.
For example, I have a table like this:
var names = new[]
{
new { FirstName = "James", LastName = "Doe", NickName = "Bobby", },
new { FirstName = "Joe", LastName = "Doe", NickName = "Joey", },
new { FirstName = "Cookie", LastName = "Monster", NickName = "Rick", },
new { FirstName = "Bob", LastName = "Magoo", NickName = "George", },
new { FirstName = "Mark", LastName = "Hsmil", NickName = "Masrkie", },
new { FirstName = "Joe", LastName = "Doe", NickName = "James", },
};
And a query like this:
string searchText = "James";
var result = names
.Where(x => x.FirstName.Contains(searchText)
|| x.LastName.Contains(searchText)
|| x.NickName.Contains(searchText));
I will get two results:
FirstName
LastName
NickName
James
Doe
Bobby
Joe
Doe
James
Is there a way I can determine from my result who matched on what column?
I Googled this reasonably, a nudge in the right direction would be appreciated.
Try this:
string searchText = "James";
var result =
names
.Select(x => new
{
name = x,
matches =
new[]
{
x.FirstName.Contains(searchText) ? "FirstName" : null,
x.LastName.Contains(searchText) ? "LastName" : null,
x.NickName.Contains(searchText) ? "NickName" : null,
}
.Where(y => y != null)
.ToArray(),
})
.Where(x => x.matches.Any());
With the very convenient sample data in your question, I get this:
I want to select only id's from List of objects in another List:
https://dotnetfiddle.net/Leu1AD
I need to use only linq Select or SelectMany:
var obj = offices.Select(p => new {Id = p.Id, Employess = p.Employess}).ToList();
Currently I get following result:
[
{
"Id":1,
"Employess":[
{
"Id":1,
"FirstName":"a",
"LastName":"b"
},
{
"Id":2,
"FirstName":"c",
"LastName":"d"
}
]
},
{
"Id":2,
"Employess":[
{
"Id":3,
"FirstName":"e",
"LastName":"f"
},
{
"Id":4,
"FirstName":"g",
"LastName":"h"
}
]
}
]
But I need this result:
[
{
"Id":1,
"Employess":[
{
"Id":1
},
{
"Id":2
}
]
},
{
"Id":2,
"Employess":[
{
"Id":3
},
{
"Id":4
}
]
}
]
Do you have any ideas how to do that?
One method to get the result to be the format you want is along the lines of
var obj = offices.Select(p => new {Id = p.Id, Employess = p.Employess.Select(y=> new {y.Id})}).ToList();
ends up as
[{"Id":1,"Employess":[{"Id":1},{"Id":2}]},{"Id":2,"Employess":[{"Id":3},{"Id":4}]}]
You need a second Select that only selects the Employee Id.
var obj = offices.Select(o => new {Id = o.Id, Employess = o.Employess.Select(e => new { Id = e.Id })});
alter your line
var obj = offices.Select(p => new {Id = p.Id, Employess = p.Employess}).ToList();
to
var obj = offices.Select(p => new {Id = p.Id, Employess = p.Employess.Select(x=>new{Id=x.Id})}).ToList();
To have the expected result just replace:
Employess = p.Employess
With
Employess = p.Employess.Select(e => new { e.Id })
Finally you have this LINQ statement:
var obj = offices.Select(p => new {Id = p.Id, Employess = p.Employess.Select(e => new { e.Id })}).ToList();
I have a list of records where I need to filter the list for duplicate records and take only one record with AddressType = "POST".
Let me show your the example:
class Test
{
public string Id {get; set;}
public string Name {get; set;}
public string AddressType {get; set;}
}
This is the data I have:
var data = new List<Test>{
new Test {Id = "1", Name = "Test11", AddressType = "POST" },
new Test {Id = "1", Name = "Test12", AddressType = "STREET" },
new Test {Id = "2", Name = "Test122", AddressType = "POST" },
new Test {Id = "3", Name = "Test123", AddressType = "POST" },
new Test {Id = "4", Name = "Test1", AddressType = "POST" },
new Test {Id = "4", Name = "Test1", AddressType = "POST" },
new Test {Id = "5", Name = "Test11", AddressType = null }
};
I'm trying to remove the duplicate records based on Id and AdressType = "POST" with this query:
var filteredData = data.GroupBy(x => x.Id).Select(x => x.First()).ToList();
This removes the duplicacy but I want to take the record with AddressType = "POST" and the above query randomly picked the First record. I have tried another thing where with this query but it is not working:
var filteredData = data.GroupBy(x => x.Id).Select(x => x.First()).Where(x => x.AddressType == "POST").ToList();
Expected Output:
Test {Id = "1", Name = "Test11", AddressType = "POST" },
Test {Id = "2", Name = "Test122", AddressType = "POST" },
Test {Id = "3", Name = "Test123", AddressType = "POST" },
Test {Id = "4", Name = "Test1", AddressType = "POST" },
Test {Id = "5", Name = "Test11", AddressType = null }
Is there anything I'm missing?
Update: Thanks to the solutions below, it worked but in case of any null value in the list. It breaks. So by adding FirstOrDefault() I'm able to handle the null error but the details of that row is not getting added to the result. Any thoughts on that?
Try putting the predicate inside the call to first:
var filteredData = data
.GroupBy(x => x.Id)
.Select(x => x.FirstOrDefault(x => x.AddressType == "POST"))
.ToList();
You can group by your selected columns then select FirstOrDefault(). try bellow;
var list = data.GroupBy(x => new { x.Id, x.AddressType })
.Select(x => x.FirstOrDefault(a => a.AddressType == "POST" || a.AddressType == null))
.Where(y => y != null)
.ToList();
Same as your expected result:
ID Name AddressType
1 Test11 POST
2 Test122 POST
3 Test123 POST
4 Test1 POST
5 Test11 null
Hope the answer helps someone.
I am using Entity Framework to create my database. I have a table called "Departments" that seed first and then add two users. I need to use the Id from the department table to seed the user table.
context.Department.AddOrUpdate(x => x.Id,
new Department() { Id = Guid.NewGuid(), Name = "System", ImageNameLight = "", ImageNameDark = "" },
new Department() { Id = Guid.NewGuid(), Name = "Estimating", ImageNameLight = "", ImageNameDark = "" },
new Department() { Id = Guid.NewGuid(), Name = "Assembly", ImageNameLight = "dep-assy-off", ImageNameDark = "dep-assy-on" },
new Department() { Id = Guid.NewGuid(), Name = "Project Engineering", ImageNameLight = "dep-pe-off", ImageNameDark = "dep-pe-on" },
);
var firstOrDefault = context.Department.FirstOrDefault(d => d.Name == "System");
if (firstOrDefault != null)
{
var user = new ApplicationUser
{
UserName = "sysadmin",
Email = "sysadmin#noemail.com",
EmailConfirmed = true,
FirstName = "System",
LastName = "Admin",
RoleId = adminRole.Id,
DateCreated = DateTime.Now,
DepartmentId = firstOrDefault.Id
};
This is what I have so far but it does not work because the user is never created.
You have to save to your context first or else the seed will never work try this :
context.Department.AddOrUpdate(x => x.Id,
new Department() { Id = Guid.NewGuid(), Name = "System", ImageNameLight = "", ImageNameDark = "" },
new Department() { Id = Guid.NewGuid(), Name = "Estimating", ImageNameLight = "", ImageNameDark = "" },
new Department() { Id = Guid.NewGuid(), Name = "Assembly", ImageNameLight = "dep-assy-off", ImageNameDark = "dep-assy-on" },
new Department() { Id = Guid.NewGuid(), Name = "Project Engineering", ImageNameLight = "dep-pe-off", ImageNameDark = "dep-pe-on" },
);
context.SaveChanges();
//Do whatever with your new context
I am using the Moq framework in my Unit Test.
This is the UpdateApplication test method:
[TestMethod]
public void UpdateApplication()
{
const string newAplpicationName = "NewApplication1";
var data =
new[]
{
new Application { Id = 1, Name = "Application1" }, new Application { Id = 2, Name = "Application2" },
new Application { Id = 3, Name = "Application3" }, new Application { Id = 4, Name = "Application4" }
}
.AsQueryable();
var mockSet = new Mock<DbSet<Application>>();
mockSet.As<IQueryable<Application>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Application>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Application>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Application>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
mockSet.Setup(m => m.AddOrUpdate(It.IsAny<Application[]>())).Callback(
(Application[] apps) =>
{
apps.FirstOrDefault(m => m.Id == 1).Name = newAplpicationName;
}).Verifiable(); // <-- Exception
var mockContext = new Mock<AppDbContext>();
mockContext.Setup(c => c.Applications).Returns(mockSet.Object);
// Act
var commandHandler = new UpdateApplicationCommandHandler(mockContext.Object);
var commandArg = new ApplicationCommandArg { Id = 1, Name = newAplpicationName };
commandHandler.Execute(new UpdateApplicationCommand(commandArg));
// Verify
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
I got an exception when ran the test:
An exception of type 'System.NotSupportedException' occurred in Moq.dll but was
not handled in user code
Additional information: Expression references a method that does not belong to
the mocked object: m => m.AddOrUpdate(It.IsAny())
at Moq.Mock.ThrowIfNotMember(Expression setup, MethodInfo method)
at Moq.Mock.c__DisplayClass19`1.b__18()
at Moq.PexProtector.Invoke[T](Func`1 function)
at Moq.Mock.Setup[T](Mock`1 mock, Expression`1 expression, Condition condition)
at Moq.Mock`1.Setup(Expression`1 expression)
at UpdateApplication() in UpdateApplicationCommandTests.cs:line 39
How should I write unit tests for update and delete actions using Moq?
This variant of UpdateApplication unit test method is working for me but I am not sure if it is correct:
[TestMethod]
public void UpdateApplication()
{
const string newAplpicationName = "NewApplication1";
var data =
new[]
{
new Application { Id = 1, Name = "Application1" }, new Application { Id = 2, Name = "Application2" },
new Application { Id = 3, Name = "Application3" }, new Application { Id = 4, Name = "Application4" }
}
.AsQueryable();
var mockSet = new Mock<DbSet<Application>>();
mockSet.As<IQueryable<Application>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Application>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Application>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Application>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<AppDbContext>();
mockContext.Setup(m => m.Applications).Returns(mockSet.Object);
// Act
var commandHandler = new UpdateApplicationCommandHandler(mockContext.Object);
var commandArg = new ApplicationCommandArg { Id = 1, Name = newAplpicationName };
commandHandler.Execute(new UpdateApplicationCommand(commandArg));
Assert.AreEqual(newAplpicationName, data.First(m => m.Id == 1).Name);
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
But I still have a problem with my DeleteApplicationCommandTest.
When I run the test I get an excepton "Expected invocation on the mock exactly 3 times, but was 2 times: m => m.Applications".
This is test method:
[TestMethod]
public void DeleteApplication()
{
var data =
new[]
{
new Application { Id = 1, Name = "Application1" }, new Application { Id = 2, Name = "Application2" },
new Application { Id = 3, Name = "Application3" }, new Application { Id = 4, Name = "Application4" }
}
.AsQueryable();
var mockSet = new Mock<DbSet<Application>>();
mockSet.As<IQueryable<Application>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Application>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Application>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Application>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<AppDbContext>();
mockContext.Setup(m => m.Applications).Returns(mockSet.Object);
// Act
var commandHandler = new DeleteApplicationCommandHandler(mockContext.Object);
var commandArg = new ApplicationCommandArg { Id = 1 };
commandHandler.Execute(new DeleteApplicationCommand(commandArg));
// Verify
mockSet.Verify(m => m.Remove(It.IsAny<Application>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
mockContext.VerifyGet(m => m.Applications, Times.Exactly(3));
}
This is my Execute method of DeleteApplicationCommandHandler:
public override void Execute(DeleteApplicationCommand command)
{
Debug.WriteLine("DeleteApplicationCommand executed");
var application = this.DbContext.Applications.FirstOrDefault(m => m.Id == command.CommandArg.Id);
if (application == null)
{
throw new Exception(string.Format("Application with id {0} was not found", command.CommandArg.Id));
}
this.DbContext.Applications.Remove(application);
this.DbContext.SaveChanges();
}
Why DeleteApplication test method fails?
The problem is that AddOrUpdate is an extension method. Moq cannot mock extension methods, so you'll need to find another way to achieve your test coverage.