I am forming an object based on list coming from input along with the string like as below.
public static LibrarySourceTableInput CreateLibrarySourceTableInput<T>(List<T> libraries, string mechanicalLibraryName)
where T : ISourceOfData
{
return new LibrarySourceTableInput()
{
LibrarySourceRowInputs = libraries?.Select(l => new LibrarySourceRowInput()
{
LibrarySourceId = l.Id,
SourceOfDataId = l.SourceOfData.Id
}).ToList() ?? new(),
MappedLibrarySource = mechanicalLibraryName
};
}
I am facing different problem here, I have libraries count coming as 1 but internal object is null for example in the below image libraries count as 1 and it is null,
and in this case I am getting a null reference exception with the above code, could any one please help on this how to avoid that null exception. Many thanks in advance.
You could do a where query before the select.
LibrarySourceRowInputs = libraries?.Where(l => l != null)
.Select(l => l => new LibrarySourceRowInput()
{
LibrarySourceId = l.Id,
SourceOfDataId = l.SourceOfData.Id
}).ToList() ?? new();
I have a table named dbo.EmployeeType with three records:
PK_EmployeetypeID EmployeeTypeName
1 Project Manager
2 Business Analyst
3 Developer
I have this piece of Linq code:
public static string GetTypeByID(int id)
{
using (ProjectTrackingEntities1 db = new ProjectTrackingEntities1())
{
var type = db.EmployeeTypes.Select(o => new LOOKUPEmployeeType
{
PK_EmployeeTypeID = id,
EmployeeTypeName = o.EmployeeTypeName
});
return type.FirstOrDefault().EmployeeTypeName;
}
}
No matter what id I send to it, it returns Project Manager, and I'm confused as to why.
You need to apply a filter, otherwise you're just returning the first record and hard coding the ID. Try this:
public static string GetTypeByID(int id)
{
using (ProjectTrackingEntities1 db = new ProjectTrackingEntities1())
{
//Here we apply a filter, the lambda here is what creates the WHERE clause
var type = db.EmployeeTypes
.FirstOrDefault(et => et.PK_EmployeeTypeID == id);
if(type != null)
{
return type.EmployeeTypeName;
}
else
{
return "";
}
}
}
Note that using FirstOrDefault means if there are no matches, or multiple matches, type will be null and you will get an empty string returned.
Set a breakpoint on type = ... and inspect it. You have no Where in there so you get all - and Select just makes LOOKUPEmployeeTypes out of all of them.
FirstOrDefault then returns the first of those 3 which is always the ProjManager
Fix:
var type = db
.EmployeeTypes
.Where( o => o.Id == id)
.Select(o => new LOOKUPEmployeeType
{
PK_EmployeeTypeID = id,
EmployeeTypeName = o.EmployeeTypeName
});
In your code you only return the first value. You need to tell EF which value you need to return.
Let us assume you need the value with Id=2. Instead of Select(), use Single(x => x.Id == 2) or First(x => x.Id == 2).
I have the below code . Here i want to find out servicelevelid in lstServiceLevels List which is an array of objects of ServiceLevelDetails where ServiceLevelName is "Basic"
Could anyone please help me to get it ?
public class ServiceLevelDetails
{
public int servicelevelid;
public string ServiceLevelName;
}
class Program
{
static void Main(string[] args)
{
IList<ServiceLevelDetails> lstServiceLevels = new List<ServiceLevelDetails>();
ServiceLevelDetails one = new ServiceLevelDetails();
one.servicelevelid=1;
one.ServiceLevelName="Basic";
ServiceLevelDetails Two = new ServiceLevelDetails();
Two.servicelevelid = 2;
Two.ServiceLevelName = "Enhanced";
lstServiceLevels.Add(one);
lstServiceLevels.Add(Two);
var test = from LevelName in lstServiceLevels
let LevelName= obj as ServiceLevelDetails
where LevelName.ServiceLevelName == "Basic"
select LevelName;
//getting error in the above code .
}
}
There is nothing in your scope called obj, so it's not clear why this is in your query.
In LINQ query syntax, it sounds like you want this:
from serviceLevel in lstServiceLevels
where serviceLevel.ServiceLevelName == "Basic"
select serviceLevel;
Or in LINQ method syntax:
lstServiceLevels.Where(x => x.ServiceLevelName == "Basic");
If, as you suggest in the comments, you want the id for a specific name:
var id = lstServiceLevels
.Where(x => x.ServiceLevelName == "Basic")
.Select(x => x.servicelevelid)
.Single();
here is an alternative with which you don't run into exceptions
when the element cannot be found.
look for the first occurrence of this element:
// FirstOrDefault will return null if nothing was found
// but it also will return only the first element!
var id_test = lstServiceLevels.FirstOrDefault(x => x.ServiceLevelName == "Basic");
// then you can check for it and take the ID if it was found
// or else assign some other value
int id = id_test != null ? id_test.servicelevelid : 0;
it's of course a matter of taste either to use try/catch or null testing :)
I have the following code:
public OrderInfo GetPreviousOrder(int customerId)
{
using (var entities = new ContosoEntities())
{
var previousOrder = entities.Orders
.OrderByDescending(x => x.CreatedDate)
.FirstOrDefault(x => x.CustomerId == customerId);
var response = new OrderInfo
{
Customer = RetrieveCustomerInfo(customerId),
};
if (previousOrder != null)
{
response.FollowUps = Mapper.Map<IEnumerable<OrderFollowUp>, OrderFollowUpData[]>(previousOrder.FollowUps);
response.Appointments = Mapper.Map<IEnumerable<Appointment>, OrderAppointment[]>(previousOrder.Appointments);
response.DiscussionTopics = previousOrder.DiscussionTopics.Select(discussionTopic => discussionTopic.Topic).ToArray();
}
var actions = new Action[]
{
() => response.Invoices = RetriveInvoices(customerId, previousOrder),
() => response.Items = RetrieveItems(customerId, previousOrder)
};
Parallel.ForEach(actions, new ParallelOptions { MaxDegreeOfParallelism = 10 }, action => action());
return response;
}
}
In summary, this method gets the info of a customer's previous order. Most of the order info is stored in my project's database (accessed using Entity Framework), but a few things are pulled from another source (customer info, invoices and items).
Sometimes, when the RetriveInvoices method gets executed (and the customer had a previous order stored in our database), the value of the previousOrder variable passed is null. Likewise, some other times, it's the RetrieveItems method that gets a null value and some other times, the code behaves as (I) expected, meaning, the previousOrder variable actually has the info of the previous order passed to both methods. Both methods are being executed until their respective last line, there are no exceptions being thrown. And no, both methods only read the previousOrder variable.
Can somebody explain to me why I'm seeing this behavior?
I have a test like this:
[TestCase("~/page/myaction")]
public void Page_With_Custom_Action(string path) {
// Arrange
var pathData = new Mock<IPathData>();
var pageModel = new Mock<IPageModel>();
var repository = new Mock<IPageRepository>();
var mapper = new Mock<IControllerMapper>();
var container = new Mock<IContainer>();
container.Setup(x => x.GetInstance<IPageRepository>()).Returns(repository.Object);
repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(() => pageModel.Object);
pathData.Setup(x => x.Action).Returns("myaction");
pathData.Setup(x => x.Controller).Returns("page");
var resolver = new DashboardPathResolver(pathData.Object, repository.Object, mapper.Object, container.Object);
// Act
var data = resolver.ResolvePath(path);
// Assert
Assert.NotNull(data);
Assert.AreEqual("myaction", data.Action);
Assert.AreEqual("page", data.Controller);
}
GetPageByUrl runs twice in my DashboardPathResolver, how can I tell Moq to return null the first time and pageModel.Object the second?
With the latest version of Moq(4.2.1312.1622), you can setup a sequence of events using SetupSequence. Here's an example:
_mockClient.SetupSequence(m => m.Connect(It.IsAny<String>(), It.IsAny<int>(), It.IsAny<int>()))
.Throws(new SocketException())
.Throws(new SocketException())
.Returns(true)
.Throws(new SocketException())
.Returns(true);
Calling connect will only be successful on the third and fifth attempt otherwise an exception will be thrown.
So for your example it would just be something like:
repository.SetupSequence(x => x.GetPageByUrl<IPageModel>(virtualUrl))
.Returns(null)
.Returns(pageModel.Object);
The existing answers are great, but I thought I'd throw in my alternative which just uses System.Collections.Generic.Queue and doesn't require any special knowledge of the mocking framework - since I didn't have any when I wrote it! :)
var pageModel = new Mock<IPageModel>();
IPageModel pageModelNull = null;
var pageModels = new Queue<IPageModel>();
pageModels.Enqueue(pageModelNull);
pageModels.Enqueue(pageModel.Object);
Then...
repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(pageModels.Dequeue);
Now you can use SetupSequence. See this post.
var mock = new Mock<IFoo>();
mock.SetupSequence(f => f.GetCount())
.Returns(3) // will be returned on 1st invocation
.Returns(2) // will be returned on 2nd invocation
.Returns(1) // will be returned on 3rd invocation
.Returns(0) // will be returned on 4th invocation
.Throws(new InvalidOperationException()); // will be thrown on 5th invocation
You can use a callback when setting up your mock object. Take a look at the example from the Moq Wiki (https://github.com/Moq/moq4/wiki/Quickstart).
// returning different values on each invocation
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
.Returns(() => calls)
.Callback(() => calls++);
// returns 0 on first invocation, 1 on the next, and so on
Console.WriteLine(mock.Object.GetCountThing());
Your setup might look like this:
var pageObject = pageModel.Object;
repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(() => pageObject).Callback(() =>
{
// assign new value for second call
pageObject = new PageModel();
});
Adding a callback did not work for me, I used this approach instead http://haacked.com/archive/2009/09/29/moq-sequences.aspx and I ended up with a test like this:
[TestCase("~/page/myaction")]
[TestCase("~/page/myaction/")]
public void Page_With_Custom_Action(string virtualUrl) {
// Arrange
var pathData = new Mock<IPathData>();
var pageModel = new Mock<IPageModel>();
var repository = new Mock<IPageRepository>();
var mapper = new Mock<IControllerMapper>();
var container = new Mock<IContainer>();
container.Setup(x => x.GetInstance<IPageRepository>()).Returns(repository.Object);
repository.Setup(x => x.GetPageByUrl<IPageModel>(virtualUrl)).ReturnsInOrder(null, pageModel.Object);
pathData.Setup(x => x.Action).Returns("myaction");
pathData.Setup(x => x.Controller).Returns("page");
var resolver = new DashboardPathResolver(pathData.Object, repository.Object, mapper.Object, container.Object);
// Act
var data = resolver.ResolvePath(virtualUrl);
// Assert
Assert.NotNull(data);
Assert.AreEqual("myaction", data.Action);
Assert.AreEqual("page", data.Controller);
}
The accepted answer, as well as the SetupSequence answer, handles returning constants.
Returns() has some useful overloads where you can return a value based on the parameters that were sent to the mocked method. Based on the solution given in the accepted answer, here is another extension method for those overloads.
public static class MoqExtensions
{
public static IReturnsResult<TMock> ReturnsInOrder<TMock, TResult, T1>(this ISetup<TMock, TResult> setup, params Func<T1, TResult>[] valueFunctions)
where TMock : class
{
var queue = new Queue<Func<T1, TResult>>(valueFunctions);
return setup.Returns<T1>(arg => queue.Dequeue()(arg));
}
}
Unfortunately, using the method requires you to specify some template parameters, but the result is still quite readable.
repository
.Setup(x => x.GetPageByUrl<IPageModel>(path))
.ReturnsInOrder(new Func<string, IPageModel>[]
{
p => null, // Here, the return value can depend on the path parameter
p => pageModel.Object,
});
Create overloads for the extension method with multiple parameters (T2, T3, etc) if needed.
Reached here for the same kind of problem with slightly different requirement.
I need to get different return values from mock based in different input values and found solution which IMO more readable as it uses Moq's declarative syntax (linq to Mocks).
public interface IDataAccess
{
DbValue GetFromDb(int accountId);
}
var dataAccessMock = Mock.Of<IDataAccess>
(da => da.GetFromDb(It.Is<int>(acctId => acctId == 0)) == new Account { AccountStatus = AccountStatus.None }
&& da.GetFromDb(It.Is<int>(acctId => acctId == 1)) == new DbValue { AccountStatus = AccountStatus.InActive }
&& da.GetFromDb(It.Is<int>(acctId => acctId == 2)) == new DbValue { AccountStatus = AccountStatus.Deleted });
var result1 = dataAccessMock.GetFromDb(0); // returns DbValue of "None" AccountStatus
var result2 = dataAccessMock.GetFromDb(1); // returns DbValue of "InActive" AccountStatus
var result3 = dataAccessMock.GetFromDb(2); // returns DbValue of "Deleted" AccountStatus
We can simply declare one variable with int as a datatype. initialize it to zero, and then increase it's value as follows:
int firstTime = 0;
repository.Setup(_ => _.GetPageByUrl<IPageModel>(path)).Returns(() =>
{
if (firstTime == 0)
{
firstTime = 1;
return null;
}
else if(firstTime == 1)
{
firstTime = 2;
return pageModel.Object;
}
else
{
return null;
}
});
In some cases one needs to have the called function return different types of data based on conditions you cannot impose via the function itself. If the function accepts parameters then those can be used as conditionals to get different data.
In my case, I had a webapi call which I need to mock; earlier it was working out fine based on the input parameter, however one fine day, those parameters were converted to request headers. So since I couldn't provide a callback (no function parameters) so came up with another approach as follows
[Earlier one, when API had parameters]
this.mockedMasterAPICalls.Setup(m => m.GetCountries(It.Is<int>(ou => ou == 2), It.Is<int>(lan => lan == 1))).Returns(Task.FromResult(countryResponse));
[New one, when API had headers... The headers were getting injected into another dictionary of the API caller]
this.mockedMasterAPICalls.Setup(m => m.RequestHeaders).Returns(new Dictionary<string, string>());
this.mockedMasterAPICalls.Setup(m => m.GetCountries()).Returns(() =>
{
if (this.mockedMasterAPICalls.Object.RequestHeaders[GlobalConstants.HeaderOUInstance] == "2")
return Task.FromResult(countryResponse);
else return Task.FromResult(new GetCountryResponse() { Countries = null });
});
Note the use of the mocked object itself to make any decisions required