I want to moq update method that is using mongodbContext. here is what i am trying to do but its not working. how to pass UpdateResult return type .ReturnsAsync<UpdateResult>(). I am very new to Mongodb database Unit Testing with .net core.
public void UpdateEventAsync_Test()
{
//Arrange
var eventRepository = EventRepository();
var pEvent = new PlanEvent
{
ID = "testEvent",
WorkOrderID = "WorkOrderID",
IsDeleted = false,
IsActive = true,
EquipmentID = "EquipmentID"
};
////Act
mockEventContext.Setup(s => s.PlanEvent.UpdateOneAsync(It.IsAny<FilterDefinition<PlanEvent>>(), It.IsAny<UpdateDefinition<Model.EventDataModel.PlanEvent>>(), It.IsAny<UpdateOptions>(), It.IsAny<System.Threading.CancellationToken>())).ReturnsAsync<UpdateResult>();
var result = eventRepository.UpdateEventAsync(pEvent);
////Assert
result.Should().NotBeNull();
Assert.AreEqual(true, result);
}
below is the code for which i want to write Moq Test
public async Task<bool> UpdateEventAsync(Model.EventDataModel.PlanEvent eventobj)
{
var filter = Builders<Model.EventDataModel.PlanEvent>.Filter.Where(f => f.ID == eventobj.ID);
// TO Do: Use replace instead of update.
var updatestatement = Builders<Model.EventDataModel.PlanEvent>.Update.Set(s => s.IsDeleted, eventobj.IsDeleted)
.Set(s => s.EquipmentID, eventobj.EquipmentID)
.Set(s => s.PlannedStartDateTime, eventobj.PlannedStartDateTime)
.Set(s => s.PlannedEndDatetime, eventobj.PlannedEndDatetime)
.Set(s => s.WorkOrderID, eventobj.WorkOrderID)
.Set(s => s.ResourceID, eventobj.ResourceID)
.Set(s => s.LastUpdatedBy, eventobj.LastUpdatedBy)
.Set(s => s.EventComment, eventobj.EventComment)
.Set(s => s.SiteID, eventobj.SiteID)
.Set(s => s.LastUpdatedDateTime, DateTime.UtcNow.ToString());
UpdateResult updateResult = await _eventContext.PlanEvent.UpdateOneAsync(filter, updatestatement);
return updateResult != null && updateResult.IsAcknowledged && updateResult.ModifiedCount > 0;
}
Either create an instance or mock UpdateResult and return that from the setup
public async Task UpdateEventAsync_Test() {
//...omitted for brevity
var mockUpdateResult = new Mock<UpdateResult>();
//Set up the mocks behavior
mockUpdateResult.Setup(_ => _.IsAcknowledged).Returns(true);
mockUpdateResult.Setup(_ => _.ModifiedCount).Returns(1);
mockEventContext
.Setup(_ => _.PlanEvent.UpdateOneAsync(It.IsAny<FilterDefinition<PlanEvent>>(), It.IsAny<UpdateDefinition<Model.EventDataModel.PlanEvent>>(), It.IsAny<UpdateOptions>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(mockUpdateResult.Object);
//Act
var result = await eventRepository.UpdateEventAsync(pEvent);
//Assert
result.Should().Be(true);
}
Also note that the test needs to be made async to be exercised accurately.
Related
Please note this error message :
System.NotSupportedException: 'Could not parse expression
'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
This overload of the method 'System.Linq.Queryable.Except' is
currently not supported.'
Is supported in newer versions of ef core?
my code :
var tuple = SearchBrand(searchTerm);
var result = GetExceptionsBrand(tuple.Item1, categoryId);
return Json(new
{
iTotalDisplayRecords = tuple.Item2,
iDisplayedBrand = result
.Skip(page * 10)
.Take(10)
.ToList(),
});
public async Task<Tuple<IQueryable<BrandDto>, int, int>>SearchBrand(string searchTerm)
{
var result = _context.Brands
.Where(c => c.IsDeleted == displayIsDeleted)
.WhereDynamic(searchTerm)
return new Tuple<IQueryable<BrandDto>, int, int>(result,
filteredResultsCount, totalResultsCount);
}
public IQueryable<BrandDto> GetExceptionsBrand(IEnumerable<BrandDto> filteredBrand, int categoryId)
{
var query = _context.CategoriesBrands.Where(x => x.CategoryId == categoryId);
var selectedList = new List<BrandDto>();
foreach (var item in query)
{
var cb = new BrandDto()
{
BrandDto_BrandId = item.BrandId
};
selectedList.Add(cb);
}
IQueryable<BrandDto> ExcpetList = filteredBrand.AsQueryable().Except(selectedList, new ComparerBrand());
return ExcpetList;
}
I have the following Entity Framework query:
IQueryable<Unit> units = context.Units;
Product product = new Product {
Conversions = model.Conversions.Select(y => new Conversion {
UnitId = units
.Where(z => z.Name == y.Unit)
.Select(z => z.Unit.Id)
.FirstOrDefault(),
Value = y.Value
}).ToList(),
Name = model.Name
}
I tried to use await before units.Where( ... as:
Product product = new Product {
Conversions = model.Conversions.Select(y => new Conversion {
UnitId = await units
.Where(z => z.Name == y.Unit)
.Select(z => z.Unit.Id)
.FirstOrDefaultAsync(),
Value = y.Value
}).ToList(),
Name = model.Name
}
This is not allowed as it is inside new Conversion ...
Shouldn't I use await? How can I use it in this query?
You can use this approach :
unitId = await Task.Factory.Start<int>(()=>{
return units.Where(z => z.Name == y.Unit)
.Select(z => z.Unit.Id)
.FirstOrDefault();
})
change int to your return type.
I map to a data transformation object when retrieving items from an ASP.NET Web API like so for a list:
public async Task<IList<PromotionDTO>> GetPromotionsList()
{
return await _context.Promotions
.Select(p => new PromotionDTO
{
PromotionId = p.PromotionId,
Is_Active = p.Is_Active,
Created = p.Created,
Title = p.Title,
BusinessName = p.BusinessName,
})
.Where(x => x.Is_Active)
.OrderByDescending(x => x.Created)
.ToListAsync();
}
And like this for getting a single record:
public async Task<PromotionDTO> GetPromotion(int id)
{
return await _context.Promotions
.Select(p => new PromotionDTO
{
PromotionId = p.PromotionId,
Is_Active = p.Is_Active,
Created = p.Created,
Title = p.Title,
BusinessName = p.BusinessName,
})
.Where(x => x.Is_Active && x.PromotionId == id)
.FirstOrDefaultAsync();
}
I'm new to DTO's and I find that I'm using the same DTO transformation code at many places, and was wondering how I can simplify my code to only do this once?
Though it may be enough to map like you've stated, but when your project starts to grow it will just complicated things and cause additional work.
I suggest that you use some kind of mapping library like AutoMapper.
https://github.com/AutoMapper/AutoMapper
static MyRepositoryConstructor()
{
// Define your maps
Mapper.Initialize(cfg => {
cfg.CreateMap<PromotionEntity, PromotionDTO>();
});
}
public async Task<IList<PromotionDTO>> GetPromotionsList()
{
return Mapper.Map<IList<PromotionDTO>>(await _context.Promotions
.Where(x => x.Is_Active)
.OrderByDescending(x => x.Created)
.ToListAsync()
);
}
public async Task<PromotionDTO> GetPromotion(int id)
{
return Mapper.Map<PromotionDTO>(await _context.Promotions
.Where(x => x.Is_Active && x.PromotionId == id)
.FirstOrDefaultAsync()
);
}
One option is to create a method which returns an IQueryable and then use that in each
Private IQueryable<PromotionDTO> Query()
{
return _context.Promotions
.Select(p => new PromotionDTO
{
PromotionId = p.PromotionId,
Is_Active = p.Is_Active,
Created = p.Created,
Title = p.Title,
BusinessName = p.BusinessName,
});
}
public async Task<IList<PromotionDTO>> GetPromotionsList()
{
return await Query()
.Where(x => x.Is_Active)
.OrderByDescending(x => x.Created)
.ToListAsync();
}
public async Task<PromotionDTO> GetPromotion(int id)
{
return await Query()
.Where(x => x.Is_Active && x.PromotionId == id)
.FirstOrDefaultAsync();
}
I am trying to hook a stream (IObservable) to be controlled through ToggleSwitch in a UWP project. The expectation is that I start the streaming when the switch is in On state and stop when it is in Off state.
So the thought is to
1. Create two commands, one to start the stream and another to stop the stream.
2. Create two Observables that monitors the switch state and InvokeCommand when the condition is right.
ViewModel
public class MainPageViewModel : ViewModelBase
{
public ReactiveCommand<Unit, (long, float)> StreamCommand { get; }
public ReactiveCommand<Unit, Unit> StopCommand { get; }
public IObservable<(long, float)> FlowStream { get; set; }
private bool _isStreamOn;
public bool IsStreamOn
{
get => _isStreamOn;
set => this.RaiseAndSetIfChanged(ref _isStreamOn, value);
}
public MainPageViewModel()
{
var stream = GetStream();
var canSwitchOn = this.WhenAnyValue(x => x.IsStreamOn);
var canSwitchOff = this.WhenAnyValue(x => x.IsStreamOn, isOn => isOn != true);
FlowStream = StreamCommand = ReactiveCommand.CreateFromObservable(
() =>
{
stream.Start();
return Observable.FromEventPattern<StreamDataEventArgs<(long, INumeric, INumeric, INumeric)>>(
h => stream.DataAvailable += h,
h => stream.DataAvailable -= h)
.SelectMany(e => e.EventArgs.Data)
.Select(item => item));
}, canSwitchOn);
StopCommand = ReactiveCommand.Create(
() =>
{
stream.Stop();
IsStreamOn = false;
}, canSwitchOff);
canSwitchOff.InvokeCommand(StopCommand);
canSwitchOn.InvokeCommand(StreamCommand);
}
}
View
public sealed partial class MainPage : Page, IViewFor<MainPageViewModel>
{
public MainPage()
{
InitializeComponent();
NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
ViewModel = new MainPageViewModel();
this.WhenActivated(subscription =>
{
subscription(this.OneWayBind(this.ViewModel,
vm => vm.StreamCommand,
v => v.chart.SeriesCollection[0].Stream)); // Chart take care of displaying data
subscription(this.Bind(this.ViewModel,
vm => vm.IsStreamOn,
v => v.streamToggle.IsOn));
});
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (MainPageViewModel)value; }
}
public MainPageViewModel ViewModel
{
get { return (MainPageViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(MainPageViewModel), typeof(MainPage), null);
}
However, the InvokeCommand fails, as it requires the ReactiveCommands to take the bool, instead of Unit.
Any idea how I can invoke a command when certain conditions are met?
If you want to turn a stream (IObservable<(long, float)> FlowStream) on and off based on a IObservable<bool> IsStreamOn observable then you can do this:
IObservable<(long, float)> outputStream =
IsStreamOn
.Select(flag => flag ? FlowStream : Observable.Never<(long, float)>())
.Switch();
So each time IsStreamOn produces a true you start getting values from FlowStream, otherwise the values stop.
This assumes that FlowStream is hot. If not, do this:
IObservable<(long, float)> outputStream =
FlowStream
.Publish(fs =>
IsStreamOn
.Select(flag => flag ? fs : Observable.Never<(long, float)>())
.Switch());
Here's a simple test:
void Main()
{
IObservable<long> outputStream =
FlowStream
.Publish(fs =>
IsStreamOn
.Select(flag => flag ? fs : Observable.Never<long>())
.Switch());
using (outputStream.Subscribe(Console.WriteLine))
{
IsStreamOn.OnNext(true);
Thread.Sleep(TimeSpan.FromSeconds(2.5));
IsStreamOn.OnNext(false);
Thread.Sleep(TimeSpan.FromSeconds(3.0));
IsStreamOn.OnNext(true);
Thread.Sleep(TimeSpan.FromSeconds(3.0));
}
}
IObservable<long> FlowStream = Observable.Interval(TimeSpan.FromSeconds(1.0));
Subject<bool> IsStreamOn = new Subject<bool>();
This produces:
0
1
5
6
7
Given the comments re actually calling .Start() and .Stop() then try something like this:
IObservable<(long, float)> outputStream =
Observable
.Create<(long, float)>(o =>
{
var stream = GetStream();
return
FlowStream
.Publish(fs =>
IsStreamOn
.Do(flag => { if (flag) stream.Start(); else stream.Stop(); })
.Select(flag => flag ? fs : Observable.Never<(long, float)>())
.Switch())
.Subscribe(o);
});
In these scenarios with your observables I tend to do
var canSwitchOn = this.WhenAnyValue(x => x.IsStreamOn).Select(_ => Unit.Default);
That will allow you not to have the bool passed along to the command.
oh also you may want a where() clause in this cause if you want to trigger a command in the right condition.
eg.
var switchOn = this.WhenAnyValue(x => x.IsStreamOn).Where(x => x).Select(_ => Unit.Default);
var switchOff = this.WhenAnyValue(x => x.IsStreamOn).Where(x => !x).Select(_ => Unit.Default);
Task: use different where clause in one query
Here is example (it is not real query, just to illustrate the problem)
var events = ctx.Events; // ctx - EntityFramework context
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
// how to get this clause from variable
.Where(ee => ee.State == gg.Key)
.Take(2)
})
.ToList();
Next code did not work, the problem is that where expression use parameter from query gg.Key
var events = ctx.Events;
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
// 1
// how to get this clause from variable
//.Where(ee => ee.State == gg.Key)
// 2
// try to take out where expression from query
.Where(_buildExpression(gg.Key))
.Take(2)
})
.ToList();
// method
static Expression<Func<Event, bool>> _buildExpression(string state)
{
return ee => ee.State == state;
}
// exeption
An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.SqlServer.dll
Additional information: variable 'gg' of type 'System.Linq.IGrouping`2[System.String,Entities.Event]' referenced from scope '', but it is not defined
Example of getting where expression from variable, but does not depend on gg.Key (wrong)
Expression<Func<Event, bool>> whereClause = (ee) => (ee.State == "test");
var events = ctx.Events;
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
// 1
// how to get this clause from variable
//.Where(ee => ee.State == gg.Key)
// 2
// try to take out where expression from query
//.Where(_buildExpression(gg.Key))
// 3
// whereClause from variable, but does not depend on gg.Key
.Where(whereClause)
.Take(2)
})
.ToList();
How to take where сlause from variable with depend on gg.Key?
p.s. the query is just example of the problem. The code below does not solve the problem of real query:
var events = ctx.Events;
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = gg.Take(2)
})
.ToList();
Solution by OP.
Thanks to Ivan Stoev comment.
Expression<Func<Event, string, bool>> whereClause = (ee, state) => (ee.State == state);
var events = ctx.Events;
var res = events
.AsExpandable() // <= add this
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
.Where(ee => whereClause.Invoke(ee, gg.Key)) // <= Invoke expression
.Take(2)
})
.ToList();
This was made possible by LinqKit