how to unit test grpc method using moq and nunit? - c#

I am trying to test out my grpc client side code which sends an authentication request to the server.
In the constructor of the class, i have:
Channel channel = new Channel(adr, ChannelCredentials.Insecure);
client = new MessageService.MessageServiceClient(channel);
and the method inside that class that i want to test is:
public void LogIn(String username, String pass)
{
try
{
String encryptedPass = StringEncrypt.Encrypt(pass, cPP, cSA, "SHA1", 2, cIV, 128);
Response res = client.LogIn(NewAuthRequest(username, encryptedPass));
if (res.Authenticated)
{
loggedIn = true;
user.UserId_ = username;
sess.Sessionid = res.Sessionid;
sess.Userid = username;
}
Console.WriteLine("Login request response: " + res.Authenticated);
}
catch (RpcException e)
{
Console.WriteLine("RPC failed " + e);
throw;
}
}
loggedin, user and sess are class variables.
i read up on how to test void methods so i was thinking of running this method in the unit test and asserting if after the method has been run, if the values of loggedin, user and sess have been changed like they should have. but i am confused about how to create moqs. StringEncrypt is a static class and the client is created using one of the grpc generated files. and i remember reading somewhere u can only create moqs of abstract classes/interfaces... so how can i create moqs for them?
thanks!!

Related

websocket sharp library Class OnMessage

I am trying to write a program that can potentially take in multiple websocket connections I am able to create a websocket connection class that will send and manipulate data how I like but I am running into a wall that I do not know how to solve.
class customWebsocket
{
public Websocket ws;
public customWebsocket(string address, int port)
{
string portString = port.ToString();
string webSend = "ws://" + address + ":" + portString;
this.ws = new WebSocket(webSend);
this.ws.Connect();
this.ws.OnMessage += this.Ws_OnMessage;
}
public void Ws_OnMessage(object sender, messageEventArgs e)
{
Console.WriteLine("THIS IS A TEST")
}
}
The initialization works however whenever I get a response from the server the "this is not a test" line does not fire and I cannot figure out why. I want to build the Ws_OnMessage into the class so that I can hopefully use the same class methods for all instances of the WebSocket by referring to the various cases as "this.ws"

FirebaseAdmin FirebaseApp Check if Firebase Instance exists

I have a C# project that subscribes multiple Registrations to a Topic. Because of the nature of the project and the fact that you cant check to see how many people have already subscribed to a Topic I need to make the following Async Calls to the server:
Subscribe Registrations
TopicManagementResponse response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(registrationTokens, topic);
Send message to Topic
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
Unsubscribe Registrations
TopicManagementResponse response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(registrationTokens, topic);
Because there are three calls I need to Create an Instance of the FirebaseApp using Credentials:
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile(path),
});
BUT because the async posts return a "WaitingForActivation" response (yet it does correctly do what it is supposed to do) I cant Delete the Instance to move on to the next function as it throws an error as it cant re-create another FirebaseApp Instance - It fails if I give it a name so I cant use GetInstance(string name).
Am I missing something or is there another way to do this.
Here is an example of a subscribe function:
internal static async Task SubscribeToTopic(string path, string topic, string regID5, string regID)
{
FirebaseApp app = FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile(path),
});
var registrationTokens = new List<string>()
{
regID5, regID
};
// Subscribe the devices corresponding to the registration tokens to the
// topic
try
{
TopicManagementResponse response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(registrationTokens, topic);
using (StreamWriter sw = System.IO.File.AppendText(HttpContext.Current.Server.MapPath("/tokens.txt")))
{
sw.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");
}
}
catch (Exception ex)
{
string myerror = ex.Message;
}
}
Any ideas?
you are creating firebase instance every time. so you need to create firebase instance in application start in global.asax file.

WCF+ duplex + Windows Form Application (ButtonClick) Trouble

I have WCF classes and now project to do. My teacher gave as to write app with streaming and duplex (I know that is impossible, but I found backdoor from this situation - I'm sending pics under 60KB).
My code worked well so far as I start wrote my GUI in Windows Form Application.
When I'm testing it via console - everything work well. But, when I want to use buttons in my GUI i have this exception:
An unhandled exception of type 'System.TimeoutException' occurred in
mscorlib.dll Additional information: This request operation sent to
net.tcp://localhost:7756/Przesylanie did not receive a reply within
the configured timeout (00:00:59.9740007). The time allotted to this
operation may have been a portion of a longer timeout. This may be
because the service is still processing the operation or because the
service was unable to send a reply message. Please consider
increasing the operation timeout (by casting the channel/proxy to
IContextChannel and setting the OperationTimeout property) and ensure
that the service is able to connect to the client.
Here bunch of code:
Service + IService (due to limitation of Stack I put it to one file):
public void WyslijstrumienNaSerwer()
{
IPrzesylanieCallback callback = OperationContext.Current.GetCallbackChannel<IPrzesylanieCallback>();
string sciezka = #"E:\5 semestr\Fras\Se płotek\Lab6\WcfServiceContractZadanie2\Host\bin\Pliki\" + "plik_odebrany.jpg";
string filePath = Path.Combine(System.Environment.SystemDirectory, sciezka);
Console.WriteLine("start");
callback.WyslijStrumien(filePath);
Console.WriteLine(filePath);
Console.WriteLine("meta");
}
namespace WcfServiceContractZadanie2
{
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IPrzesylanieCallback))]
public interface IPrzesylanie
{
[OperationContract]
void WyslijstrumienNaSerwer();
}
[ServiceContract]
public interface IPrzesylanieCallback
{
[OperationContract(IsOneWay = true)]
void WyslijStrumien(string filePath);
}
}
Client + callback + form + References.cs:
namespace Aplikacja
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
PrzesylanieClient klient = new PrzesylanieClient(new InstanceContext(new PrzesylanieCallback()), "NetTcpBinding_IPrzesylanie");
klient.WyslijstrumienNaSerwer();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public class PrzesylanieCallback : Referencja1.IPrzesylanieCallback
{
public void WyslijStrumien(string filePath)
{
Form1 o1 = new Form1();
// Pobieranie obrazka od klienta
string sciezka = #"E:\5 semestr\Fras\Se płotek\Lab6\WcfServiceContractZadanie2\Aplikacja\bin\Pliki\" + o1.wybrany();
string filePathZrodla = Path.Combine(System.Environment.SystemDirectory, sciezka);
//Otwieranie obrazka
Stream strumien = null;
try
{
FileStream imageFile = File.OpenRead(filePathZrodla);
strumien = (Stream)imageFile;
}
catch(IOException ioe)
{
Console.WriteLine("Wyjatek otwierania pliku: {0}", ioe.ToString());
Console.ReadKey();
throw ioe;
}
// Zapisywanie obrazka
o1.SaveFile(strumien, filePath);
}
}
}
private void btnPrzeslijPlikNaSerwer_Click(object sender, EventArgs e)
{
PrzesylanieClient klient = new PrzesylanieClient(new InstanceContext(new PrzesylanieCallback()), "NetTcpBinding_IPrzesylanie");
klient.WyslijstrumienNaSerwer();
}
public void WyslijstrumienNaSerwer() {
base.Channel.WyslijstrumienNaSerwer();
}
I wrote methods SaveFile which works correctly.
As you see, I'm testing my code in the begining of Main function in Client and that works well.
But when I'm using the same code in Forms it does not work. Compiler is returnig me to References.cs and gives me exception I mentioned earlier.
Waiting for any respone!
My answer does not solve your exception issue; however, it might prevent you from getting a very bad grade. Streaming AND duplex are both supported in WCF.
Streaming:
https://msdn.microsoft.com/en-us/library/ms733742(v=vs.110).aspx
Duplex:
https://msdn.microsoft.com/en-us/library/ms731064(v=vs.110).aspx

Proxy does not accept offered credentials. C# remoting

I'm having trouble with a proxy server which won't accept the authentication details my application is offering it. Here is what I'm doing:
private bool DoLoginTest(WebProxy wp = null)
{
if(MMremotingClient.LoginWCP(wp) == AdminNetworkFlags.CLIENTPOS)
{
FL.Log("Test licensing server connection REM finished");
FL.Log("Connection could be established successfully");
MMremotingClient.DoTask(BitConverter.GetBytes((int)AdminNetworkFlags.CLIENTEND), "Nothing");
MMremotingClient.DisableFLogging();
Invoke(txtDelegate, " finished\r\n");
return true;
}
else
{
FL.Log("Test server connection failed!");
FL.Log("NoTask");
Invoke(txtDelegate, " failed\r\n");
Invoke(MBDelegate, "Could not reach the licencing server. Please make sure that no firewall is blocking port 80, or that your computer is allowed to access the internet.");
return false;
}
}
In a series of tests, i try to connect to a server with the old remoting protocol (upgrade to WCF not possible atm). If the DoLoginTest Method fails, the user will see a little form where he can enter the proxy details which get injected into the HTTPClientChannel object. Then another try to connect to the Server is made.
public static AdminNetworkFlags LoginWCP(WebProxy wProx = null)
{
FileLogger.Log("MMLC: LoginWCP");
Register(wProx);
return Login();
}
private static void Register(WebProxy iwp = null)
{
FileLogger.Log("MMLC: Register");
try
{
IDictionary props = new Hashtable();
if(iwp == null)
{
props["useDefaultCredentials"] = true;
}
else
{
NetworkCredential nc = (NetworkCredential)iwp.Credentials;
if(nc != null)
{
props["domain"] = nc.Domain ?? null;
props["password"] = nc.Password;
props["username"] = nc.UserName;
props["useDefaultCredentials"] = false;
}
else
{
props["domain"] = null;
props["password"] = "1234";
props["username"] = "u.name";
props["useDefaultCredentials"] = false;
}
}
ServicePointManager.Expect100Continue = false;
HttpChan = new HttpClientChannel(props, new BinaryClientFormatterSinkProvider());
SetChannelProxy(HttpChan, iwp ?? WebRequest.GetSystemWebProxy());
FileLogger.Log("MMLC: RegChannel");
ChannelServices.RegisterChannel(HttpChan, true);
RemoteObject = (IRemObject)Activator.GetObject(typeof(IRemObject), "http://someAdress:80/IRemObject");
FileLogger.Log("MMLC: connected");
}
catch(Exception x)
{
Trace.WriteLine("Error connecting to remote server, reason: " + x.Message);
RemoteObject = null;
}
}
private static void SetChannelProxy(HttpClientChannel channel, IWebProxy proxy)
{
FieldInfo proxyObjectFieldInfo = typeof(HttpClientChannel).GetField("_proxyObject", BindingFlags.Instance | BindingFlags.NonPublic);
proxyObjectFieldInfo.SetValue(channel, proxy);
}
This is the Form asking the user for Proxy details. If the User ends it with hitting the "OK" button on it, the defined Proxy property is set. That property is then passed to the LoginWCP() function.
private void button1_Click(object sender, EventArgs e)
{
definedProxy = new WebProxy(txtAdress.Text, decimal.ToInt32(nudPort.Value));
Address = txtAdress.Text;
Port = decimal.ToInt32(nudPort.Value);
NetworkCredential nc = new NetworkCredential()
{
Domain = string.IsNullOrWhiteSpace(txtDomain.Text) ? null : txtDomain.Text,
UserName = txtName.Text,
Password = txtPassword.Text
};
definedProxy.Credentials = nc;
DialogResult = System.Windows.Forms.DialogResult.OK;
Close();
}
So far this worked fine, but now I have the first user with an proxy in an Active Directory Environment. As i am lacking an AD, i cannot test the application in it. So I am asking you, is there anything wrong with my application? Do i need to check the user ipnut for something? is the Expect100Continue = falsedoing something bad?
So, this thing happened again, but this time it could be solved. First I have to name the culprit giving me a hard time. ZScaler. This software suite build around blocking and sniffing into connections from the outside and inside seems to only allow connections to adresses, and not direct IPs. Up to this point my application directly connected to an IP, instead of an real adress. Some Changes later, my server is now browsable by an address, and the application is let through by the proxy of the ZScaler.

SignalR Can I pass a DataSet

I have a SignalR application in two parts. I have basic messaging going back and forth between an MVC app (SignalR Server) and the Windows Service (SignalR Client). The Windows Service is on a back-end machine that has the AdventureWork2012 database on it. Management desires that the Windows Service - SignalR client query the database and send back a DataSet via SignalR. Can SignalR pass DataSets? I am getting an exception "Invalid URI: The Uri string is too long." in the event log when I call the server method.
Here is the MVC Server Hub:
public class AlphaHub : Hub
{
public void Hello(string message)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
Clients.All.addNewMessageToPage(message);
// Call Windows Service
string message1 = System.Environment.MachineName;
Clients.All.Notify(message1);
}
public void Register(string registrationID,string connectionID)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
System.Web.HttpContext.Current.Application["registrationID"] = registrationID + "|" + connectionID;
}
public void RecieveDataSet(DataSet ds)
{
Clients.All.addNewMessageToPage("Data Set recieved");
}
Here is the Windows Service Code that throws an exception on the line:
await alphaProxy.Invoke("RecieveDataSet", employees);
The code is:
protected override async void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
try
{
var hubConnection = new HubConnection("http://www.someurl.com/signalr", useDefaultUrl: false);
IHubProxy alphaProxy = hubConnection.CreateHubProxy("AlphaHub");
await hubConnection.Start();
string cid = hubConnection.ConnectionId.ToString();
eventLog1.WriteEntry("ConnectionID: " + cid);
// Invoke method on hub
await alphaProxy.Invoke("Hello", "Message from Service - ConnectionID: " + cid + " - " + System.Environment.MachineName.ToString() + " " + DateTime.Now.ToString());
await
alphaProxy.Invoke("Register", "81577f58-0e05-43f4-b322-fbf0d9d1e79e",
hubConnection.ConnectionId.ToString());
alphaProxy.On("addNewMessageToPage", () => eventLog1.WriteEntry("Notified!"));
DataSet employees = new DataSet();
string connString = "...";
SqlConnection conn = new SqlConnection(connString);
string queryString = "SELECT * FROM [HumanResources].[Employee]";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, conn);
adapter.Fill(employees, "HumanResources.Employee");
await alphaProxy.Invoke("RecieveDataSet", employees);
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
Is it possible to pass a DataSet? If not, do I have to serialize/deserialize? If so, can you show the code to do that?
You want to keep your messages pretty lightweight with SignalR for many reasons (especially with scale-out via backplanes), so I would NOT pass something big like a DataSet via a SignalR message personally. What I usually suggest for larger payloads is that you send a specific message that tells the browser it should update that data which it then does by downloading using a traditional GET to some kind of REST based service. This way you have real-time notifications of updates, but you're using traditional HTTP GET to transfer the actual payload.
I recommend you convert your dataset into a Data Transfer Object and pass that. With SignalR, you could pass each object as it is hydrated allowing you to notify observers not only when you fetch, but also whenever any new item is added as well. I haven't tested this code, so I may well have missed something, but it should give you the idea.
adapter.Fill(employees, "HumanResources.Employee");
foreach (var dr in employees)
{
var empDto = new EmployeeDto
{
FirstName = dr.Fields("FirstName"),
LastName = dr.Fields("LastName"),
// Additional fields go here...
};
alphaProxy.Clients.ReceiveDataSet(empDto); // Serializes the dto as json by default.
}
Of course, if you want to send the full list in the response you should be able to modify this slightly:
adapter.Fill(employees, "HumanResources.Employee");
var items = new List<EmployeeDto>();
foreach (var dr in employees)
{
var empDto = new EmployeeDto
{
FirstName = dr.Fields("FirstName"),
LastName = dr.Fields("LastName"),
// Additional fields go here...
};
items.Add(empDto);
}
alphaProxy.Clients.ReceiveDataSet(items); // Serializes the dto as json array by default.
http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-net-client#clientmethodswithoutparms
See the guide of passing methods with and without params.

Categories