I created an ASP.NET project and wrote some integration tests for it. But when I tried to run dotnet test this shows up:
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
The active test run was aborted. Reason: Test host process crashed : Unknown command: --environment=Development
Test Run Aborted with error System.Exception: One or more errors occurred.
---> System.Exception: Unable to read beyond the end of the stream.
at System.IO.BinaryReader.Read7BitEncodedInt()
at System.IO.BinaryReader.ReadString()
at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable()
at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action`1 errorHandler, CancellationToken cancellationToken)
--- End of inner exception stack trace ---.
As I understand something tries to run dotnet executable with --environment=Development but this argument is invalid even though it is used in Microsoft docs.
I tried creating new ASP.NET project (no controllers, services, database etc. just API that does nothing and an empty test) but I couldn't reproduce the error again.
Initially I created my project and solution in the same folder by accident and had to manually move project to subfolder. Everything worked fine after I did that so I assumed it's fine. Maybe that is the reason.
Here's how I access application during testing:
// TestingApplication.cs
public class TestingApplication : WebApplicationFactory<Program>
{
private readonly Guid _appId = Guid.NewGuid();
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
// Add mock/test services to the builder here
builder.ConfigureServices(services =>
{
services.AddMvcCore().AddApplicationPart(typeof(Program).Assembly);
services.AddScoped(sp => new DbContextOptionsBuilder<EfDbContext>()
.UseSqlServer(
$"DATABASE CONNECTION STRING")
.UseApplicationServiceProvider(sp)
.Options);
});
}
protected override IHost CreateHost(IHostBuilder builder)
{
var host = base.CreateHost(builder);
using (var serviceScope = host.Services.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<EfDbContext>();
context.Database.EnsureCreated();
}
return host;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
using (var serviceScope = Server.Services.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<EfDbContext>();
context.Database.EnsureDeleted();
}
}
}
// BaseTest.cs
public class BaseTest : IDisposable, IClassFixture<TestingApplication>
{
protected readonly TestingApplication Application;
private HttpClient? _client;
protected HttpClient Client => _client ??= Application.CreateClient();
public BaseTest(TestingApplication testingApplication)
{
Application = testingApplication;
}
public void Dispose()
{
Application.Dispose();
}
}
Some more info:
Unit tests work just fine
Initially I forgot to add <InternalsVisibleTo Include="NameOfTestsProject" /> to the main project file, but it doesn't work either way.
.NET 6, OS - Linux, IDE - Jetbrains Rider
Rebuilding solution does not work
Creating new project for unit tests doesn't help either
Does anyone know what the problem is?
UPD I figured it out
Okay, So this is just another example of copy-pasting someone else's code without checking. I had copied something along the lines of:
if (args[0] == "something") {
...
} else if (args[0] == "something else") {
...
} else {
// exit with code 1 here and print error
}
in my Program.cs. It worked fine by itself but when testing it caused this problem.
Related
My company is using 2 Windows servers. 1 Server is running as a backup server and other than SQL replication, the backup server requires manual intervention to get it running as the primary. I have no control over this, but I do have control of the apps/services running on the servers.
What I have done is I got all the services to be running on both and added Rabbit MQ as a clustered message broker to kind of distribute the work between the servers. This is all working great and when I take a server down, nothing is affected.
Anyway, to the point of the question, the only issue I see is that the services are using the same SQL server and I have nothing in place to automatically switch server if the primary goes down.
So my question is, is there a way to get Entity Framework to use an alternative connection string should one fail?
I am using the module approach with autofac as dependency injection for my services. This is the database registration.
public class AppsDbModule : Module
{
protected override void Load(ContainerBuilder builder)
{
RegisterContext<AppsDbContext>(builder);
}
private void RegisterContext<TContext>(ContainerBuilder builder) where TContext : DbContext
{
builder.Register(componentContext =>
{
var serviceProvider = componentContext.Resolve<IServiceProvider>();
var configuration = componentContext.Resolve<IConfiguration>();
var dbContextOptions = new DbContextOptions<TContext>(new Dictionary<Type, IDbContextOptionsExtension>());
var optionsBuilder = new DbContextOptionsBuilder<TContext>(dbContextOptions)
.UseApplicationServiceProvider(serviceProvider)
.UseSqlServer(configuration.GetConnectionString("AppsConnection"),
serverOptions => serverOptions.EnableRetryOnFailure(5, TimeSpan.FromSeconds(30), null));
return optionsBuilder.Options;
}).As<DbContextOptions<TContext>>()
.InstancePerLifetimeScope();
builder.Register(context => context.Resolve<DbContextOptions<TContext>>())
.As<DbContextOptions>()
.InstancePerLifetimeScope();
builder.RegisterType<TContext>()
.AsSelf()
.InstancePerLifetimeScope();
}
}
and my appsettings.json as this
"ConnectionStrings": {
"AppsConnection": "Data Source=primary;Initial Catalog=Apps;User Id=me;Password=topsecret"
}
Couldn't really find anything on the web, other than posts where you was in full control of creating the db connection, but I am being supplied the connection via DI.
Using .Net 5 and the applications are worker services.
You can define on custom retry strategy on implementing the interface IExecutionStrategy.
If you want reuse the default SQL Server retry strategy, you can derive from SqlServerRetryingExecutionStrategy on override the method ShouldRetryOn :
public class SqlServerSwitchRetryingExecutionStrategy : SqlServerRetryingExecutionStrategy
{
public string _switchConnectionString;
public SqlServerSwitchRetryingExecutionStrategy(ExecutionStrategyDependencies dependencies, string switchConnectionString)
: base(dependencies, 3)
{
_switchConnectionString = switchConnectionString;
}
protected override bool ShouldRetryOn(Exception exception)
{
if (exception is SqlException sqlException)
{
foreach (SqlError err in sqlException.Errors)
{
switch (err.Number)
{
// For this type of error, switch the connection string and retry
case 1418: // The server can't be reached or does not exist
case 4060: // Cannot open database
case 4064: // Cannot open user default database database
var db = Dependencies.CurrentContext.Context.Database;
var current = db.GetConnectionString();
if(current != _switchConnectionString)
db.SetConnectionString(_switchConnectionString);
return true;
}
}
}
return base.ShouldRetryOn(exception);
}
}
I am not sure which errors to catch for your scenario.
You should test and find the errors to handle.
The full list is available Database engine errors.
To inject the strategy :
new DbContextOptionsBuilder<TContext>(dbContextOptions)
.UseSqlServer(
configuration.GetConnectionString("AppsConnection"),
serverOptions => serverOptions.ExecutionStrategy(dependencies =>
new SqlServerSwitchRetryingExecutionStrategy(
dependencies,
configuration.GetConnectionString("AppsConnectionBackup"))
)
);
If you want a full custom strategy, you can get inspiration from SqlServerRetryingExecutionStrategy.
I took over a project is ASP.NET, C# and React which is not too well documented. In Visual Studio (Professional 2017)'s debug mode, I initially keep getting a bunch of errors which I ignore by clicking Continue a couple of times. The Output within Visual Studio reads:
An exception of type 'System.Web.Http.HttpResponseException' occurred in myProject.API.dll but was not handled in user code
Processing of the HTTP request resulted in an exception.
Please see the HTTP response returned by the 'Response' property of this exception for details.
The corresponding code is probably myProject.BSTB.API\Filters\UserAuthenticationFilter.cs:
namespace myProject.API.Filters
{
public class UserAuthenticationFilter : ActionFilterAttribute
{
// ... some other code
public override void OnActionExecuting(HttpActionContext actionContext)
{
var name = HttpContext.Current.User.Identity.Name;
ServiceLocator sl = new ServiceLocator();
User user = null;
try { user = sl.User.GetUserByName(name); } catch (Exception ex) { throw; }
if (user == null)
{
throw new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.Unauthorized) {
ReasonPhrase = "Unauthorize request: User not valid: " + name});
}
HttpContext.Current.Items.Add(Common.CURRENT_CONTEXT_USER, user);
base.OnActionExecuting(actionContext);
}
}
}
I was told:
Since the system uses NTLM authentication and credentials are not sent on the first call to the server, the server sends an error response, and the credentials are sent with the second request. Thus it is expected that the server will have user == null towards the beginning, and spit out a lot of HTTP errors, this is the desired behaviour.
Edit: I believe that we are actually rather using Kerberos and we actually performing an authorization rather than an authentication, see e.g. Authentication versus Authorization.
Interestingly, other developers cannot reproduce this issue, so it might have to do something with the way I set up Visual Studio.
Clearly it is a waste of time that I have to click several times on the Continue button each time when I start running the code in Visual Studio. How should I adjust the code that this error does not show up any more? Is there maybe just a configuration in Visual Studio or some additional code I should add?
Edit
The user comes from an additional service my.Service\UserService.cs which reads
namespace myProject.Service
{
public class UserService
{
private projectContext _db;
internal UserService(projectContext db)
{
_db = db;
}
public User GetUserByName(string name)
{
return _db.Users.SingleOrDefault(x => x.UserName == name);
}
I'm seeing odd behavior while attempting to debug xUnits against components of the asp.net core pipeline. The code posted below has all purposeful functionality stripped out to illustrate the problem only which is :
Not hitting all my breakpoints in JsonModelBinder.
Not exiting on "return Task.Completed" even though it's being evaluated.
The production code for JsonModelBinder contains more logic to deserialize the incoming string data. This code contains failure logic which contains a number of return Task.Completed statements. When using this code the the debugger will evaluate these return statements but continue onward, not returning until reaching the end of the method, always reaching the end.
I'm using Moq, xUnit, VS2017, ASP.net Core 2.2.
// Simple fact
[Fact]
public async Task BindModelAsync_WithNullValueProvider_SetsDefaultError()
{
// arrange
var queryStringCollection = new RouteValueDictionary
{
{"Page", "1"},
{"Size", "20"}
};
var valueProvider = new RouteValueProvider(BindingSource.Path, queryStringCollection);
ModelBindingContext bindingContext = new DefaultModelBindingContext
{
ModelName = "Test",
ValueProvider = valueProvider
};
var jsonBinder = new JsonModelBinder();
// act
await jsonBinder.BindModelAsync(bindingContext);
// not point in asserting :-)
}
// JsonModelBinder
public class JsonModelBinder : IModelBinder
{
private readonly IOptions<MvcJsonOptions> _jsonOptions;
private readonly ILoggerFactory _loggerFactory;
public JsonModelBinder() { }
public Task BindModelAsync(ModelBindingContext bindCtx)
{
string modelName = bindCtx.ModelName;
Debug.Print(modelName);
if (string.IsNullOrEmpty(modelName))
{
return Task.CompletedTask;
}
return Task.CompletedTask;
}
}
** Edit for Project Refs
One of my colleagues encountered the same problem.
After a lot of debugging and investigation, we found this fixed the problem for him.
Right-click on the solution in Visual Studio and do a ‘Clean Solution’.
Manually delete the contents of the obj and bin folders of the projects.
Delete the contents of the .vs folder in the solution root. (if the files are locked, close Visual Studio.)
The last step seems to be the important part.
I am developing a Universal windows app and its working fine on Windows Phone, Phone Emulators but when I try to run this on local machine (desktop) it keep exiting with message " App has exited with code 1" which I think someone send an exit signal with 1, but why ...? no info available.
I found some related questions but non of them have definite answer.
Any help and suggestions would be appreciated.
App.xaml.cs code
public App()
{
this.InitializeComponent();
this.ExtendedSplashScreenFactory = (splashscreen) => new ExtendedSplashScreen(splashscreen);
#if DEBUG
HockeyClient.Current.Configure("Appid");
HockeyClient.Current.SendCrashesAsync();
#endif
// start live tiles updates
SportsClassLibrary.Common.SportsLiveTiles.StartPeriodicTileUpdate("https://tve.rpc.org/windows/sportsTile.cgi");
}
protected override Task OnInitializeAsync(IActivatedEventArgs args)
{
_container.RegisterType<IAlertDialogService, AlertDialogService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IAccountService, AccountService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IConfigService, ConfigServices>(new ContainerControlledLifetimeManager());
_container.RegisterInstance <INavigationService>(this.NavigationService);
_container.RegisterInstance<IEventAggregator>(new EventAggregator());
ServiceLocator.SetUnityContainer(_container);
// override the default viewmodel assembly location
Prism.Mvvm.ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
{
var viewModelTypeName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "SportClassLibrary.ViewModels.{0}ViewModel,SportClassLibrary", viewType.Name);
var viewModelType = Type.GetType(viewModelTypeName);
return viewModelType;
});
return Task.FromResult<object>(null);
}
protected override object Resolve(Type type)
{
return _container.Resolve(type);
}
protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
if (args.PreviousExecutionState != ApplicationExecutionState.Running)
{
IConfigService configServices = (IConfigService)ServiceLocator.getServiceInstanceForType(typeof(IConfigService));
await configServices.GetConfigAsync();
}
this.NavigationService.Navigate(Experiences.Experience.Epg.ToString(), null);
}
}
All methods execute fine
Okay I found the issue, actually I was sending crash report to hockey asynchronously in constructor method, HockeyClient.Current.SendCrashesAsync(); moving this code to OnInitializeAsync method fix this issue.
I experience a strange issue while testing my Nhibernate repositories.
I have 10 unit-tests like the ones below. Everytime a run them in a batch the first fails and the rest succeeds. If a run them one by one they all fail. If a restart MSDTC before my testrun it sometimes behaves like before and sometimes all tests succeeds. I can´t find a pattern why it behaves like that.
I want the transaction to rollback so that a start with a clean DB for every test, therefore the transaction disposal.
The test/tests are failing due to this error:
System.Data.SqlClient.SqlException: MSDTC on server 'MYCOMPUTERNAME\SQLEXPRESS' is unavailable.
My tests looks like this:
[TestInitialize]
public void MyTestInitialize()
{
_transactionScope = new TransactionScope();
}
[TestCleanup]
public void MyTestCleanup()
{
if (_transactionScope != null)
{
_transactionScope.Dispose();
_transactionScope = null;
}
}
[TestMethod]
[TestCategory("RepositoryTests")]
public void RepositoryCanSaveAProduct()
{
var platform = ProductObjectMother.CreatePlatform("100010", "Supplier 10");
var mainsegment = ProductObjectMother.CreateMainSegment("123");
var application = ProductObjectMother.CreateApplication("Foo");
var productfamily = ProductObjectMother.CreateProductFamily("X99");
Engine i = ProductObjectMother.CreateEngine(platform, productfamily, application, mainsegment);
var repository = new ProductRepository();
repository.Save(i);
repository.Flush();
}
Problem seems to be with transaction that is neither committed using _transactionScope.Complete() or roll back by throwing exception.
Also I notice one strange thing, test usually fails or run successfully by "Assert" functions(equals, not equal, exists etc from assert) that is missing from your test. :)