Imagine that you have a function that checks if the provided string value is empty like below:
string IsNotEmpty(string value)
{
if (!string.IsEmpty(value)) return value
else throw new Exception("Value is empty");
}
Also imagine that we have many other parts of our code that call this generic function to check if there is a value and if not throw a more specific exception than the generic one. As an example i will provide the below code:
string CheckEmail(string email)
{
try
{
return IsNotEmpty(email);
}
catch(Exception ex)
{
throw new **EmptyEmailException**("Please provide your email");
}
}
Now i want to write a MSTest for the CheckEmail function that expects an exception of type EmptyEmailException to be thrown. But unfortunately the test captures only the generic Exception from IsNotEmpty function, it stops execution and the code never tests the second exception.
Things i have done without any success:
I wrote my test with ExpectedException attribute.
I wrote my test
with Assert.ThrowsException.
I updated the exception settings in VS
to not brake on exceptions of type Exception, just to see if that
will resolve my issue.
No matter what i do MSTest always reports the first exception and of course my test fails. Below is my current test code:
[TestMethod]
public void When_Validating_SignInRequest_And_Email_IsEmpty_Raise_EmptyEmailException()
{
var ex = Assert.ThrowsException<EmptyEmailException>(
() => CheckEmail(string.Empty)
);
}
Can anyone point me to the right direction?
Thanks.
This works fine on my end:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace MyNamespace
{
public class EmptyEmailException : Exception
{
public EmptyEmailException(string message) : base(message)
{ }
}
public class MyClass
{
public static string IsNotEmpty(string value)
{
if (!string.IsNullOrEmpty(value))
return value;
else
throw new Exception("Value is empty");
}
public static string CheckEmail(string email)
{
try
{
return IsNotEmpty(email);
}
catch
{
throw new EmptyEmailException("Please provide your email");
}
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Assert.ThrowsException<EmptyEmailException>(() => MyClass.CheckEmail(string.Empty));
}
}
}
Related
I have an ExceptionTest class where I store the Tests for each of the classes. I have quite a few methods where I am repeating the same structure.
public class ExceptionTest {
#Test
void conversionException() {
assertThrows(ConversionException.class, () -> {
try {
throw new ConversionException();
} catch (QOException ex) {
assertEquals("Error converting", ex.getMessage());
assertEquals(417 /* FAILED */, ex.getHttpStatus());
assertEquals(ErrorCodes.DOCUMENT_ERROR, ex.getCode());
throw ex;
}
});
}
#Test
void userException() {
assertThrows(UserException.class, () -> {
try {
Integer maxUsers = 5;
throw new UserException(maxUsers);
} catch (QOException ex) {
Integer maxUsers = 5;
assertEquals("Excedido "+ maxUsers +" disp", ex.getMessage());
assertEquals(403 /* FORBIDDEN */, ex.getHttpStatus());
assertEquals(ErrorCodes.USERS, ex.getCode());
throw ex;
}
});
}
}
From what I have read in Spring you can use the #ParameterizedTest annotation in a separate class and call that class from each Test method, and collect it from the method parameterized with the #MethodSource annotation.
This is the code I am looking for:
#ParameterizedTest
#MethodSource("stringProvider")
void testWithExplicitLocalMethodSource(String argument) {
assertNotNull(argument);
}
The problem is that I do not apply it to the classes I have in Test. How do I have to create the method in a separate class to apply the structure to all the Tests that are in the ExceptionTest class?
Your question seems familiar to an article posted by Baeldung.com; where they gave this as example:
class StringsUnitTest {
#ParameterizedTest
#MethodSource("com.baeldung.parameterized.StringParams#blankStrings")
void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) {
assertTrue(Strings.isBlank(input));
}
}
public class StringParams {
static Stream<String> blankStrings() {
return Stream.of(null, "", " ");
}
}
When performing inline edit in a jquery/jqgrid table, I am seeing the ID (PK) and the column values come across to my public IActionResult Edit URL with a 200 response. However I am then encountering an error where my DBContext does not exist, however it's the same dbcontext I used to retrieve the data. Also, not able to return a string message? The code up until my Edit works, what am I doing wrong?
namespace MyProject.Controllers
{
public class CheckRequestController : Controller
{
private readonly MyDBContext _context;
public CheckRequestController(MyDBContext context)
{
_context = context;
}
public IActionResult Index()
{
return View();
}
public IActionResult LoadData()
{
try
{
var fileData = (from tempFile in _context.CheckRequest
select tempFile);
var data = fileData.ToList();
return Json(data);
}
catch (Exception)
{
throw;
}
}
// I'm trying to run an update to the row in SQL Server. I see my ID and the values come across 200 status but can't update.. Also can't return string from IAction
// Also can't return string from IActionResult or ActionResult. How to return message if failure
public IActionResult Edit(CheckRequest checkrequests)
{
try
{
if (ModelState.IsValid)
{
using (MyDBContext db = new MyDBContext())
{
db.Entry(checkrequests).State = EntityState.Modified;
db.SaveChanges();
}
}
}
catch (Exception ex)
{
//msg = "Error occured:" + ex.Message;
var msg = new string[] { "Error occured:" + ex.Message };
}
return msg;
}
}
}
I removed the readonly and was able to trace the server and see the request coming across; can't believe my eyes didn't catch that. Still curious how to capture and return an error message that's useful though on the return in the IActionResult. Right now I changed it to return Ok() so it's not really useful if an error is to occur.
I have the following controller which takes guids in string format as query parameters.
I wanted to verify they were a valid guid before executing the method but I'm not sure how to fire my custom ValidationAttribute:
controller.cs
public async Task<Profile> GetProfile([ValidGuid] string id)
{
...
}
ValidGuidAttribute.cs
internal class ValidGuidAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
try
{
Guid.Parse(value.ToString());
return true;
}
catch (Exception e)
{
throw new InvalidIdException($"{value.ToString()} is an invalid id");
}
}
}
Any help pointing out how to fire my IsValid method would be appreciated.
You should use a route constraint https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#route-constraints
[Route("getprofile/{id:guid}")]
public async Task<Profile> GetProfile(string id)
{
...
}
I have the following sample TFS CheckIn Policy:
[Serializable()]
public class AuditControlsPolicy : PolicyBase
{
public List<string> list;
public AuditControlsPolicy() : base()
{
list = new List<string>() { "a", "b", "c" };
System.Windows.Forms.MessageBox.Show("in constructor");
}
public override string Description
{
get { return "my description"; }
}
public override string Type
{
get { return "my policy"; }
}
public override string TypeDescription
{
get { return "description"; }
}
public override string InstallationInstructions
{
get { return "install instructions"; }
}
public override Microsoft.TeamFoundation.VersionControl.Client.PolicyFailure[] Evaluate()
{
List<PolicyFailure> policyFailures = new List<PolicyFailure>();
if (list == null)
System.Windows.Forms.MessageBox.Show("list is null");
else
System.Windows.Forms.MessageBox.Show(String.Join(",", list.ToArray()));
return policyFailures.ToArray();
}
public override void DisplayHelp(PolicyFailure failure)
{
MessageBox.Show("No help available at this time");
}
public override void Activate(PolicyFailure failure)
{
MessageBox.Show(failure.Message);
}
protected override void OnPolicyStateChanged(PolicyFailure[] failures)
{
base.OnPolicyStateChanged(failures);
}
public override void Initialize(IPendingCheckin pendingCheckin)
{
base.Initialize(pendingCheckin);
pendingCheckin.PendingChanges.CheckedPendingChangesChanged += PendingCheckinCheckedPendingChangesChanged;
}
public override void Dispose()
{
PendingCheckin.PendingChanges.CheckedPendingChangesChanged -= PendingCheckinCheckedPendingChangesChanged;
base.Dispose();
}
private void PendingCheckinCheckedPendingChangesChanged(object sender, EventArgs e)
{
OnPolicyStateChanged(Evaluate());
}
public override bool Edit(IPolicyEditArgs policyEditArgs)
{
return true;
}
}
It is properly registered and "works" -- however, it appears that the instance member field list is not initialized when the Evaluate method is called.
When I toggle to Pending Changes view in Visual Studio with at least one pending change I get the message box of "In Constructor" multiple times. This is followed by "list is null", even though I clearly initialize the field in my instance constructor. If I declare my list as a static and initialize it in the instance constructor, then it display my list of values.
It almost seems as if Visual Studio is invoking the Evaluate method on a static object, even though it is not declared as such.
Is the Evaluate method being invoked as a static? Am I missing something about how I should be constructing my Policy Object?
Evaluate method shouldn't be invoked on a static class and the Visual Studio also will not invoke the Evaluate method on a static object. There must be something wrong in your code, try to move list = new List<string>() { "a", "b", "c" }; to public override void Initialize(IPendingCheckin pendingCheckin) and try again.
According to your description and code, guess the Evaluate() method had being invoked on the parent class PolicyBase before AuditControlsPolicy, that's why you got the list is nul.
Im made a sort of autentication on my web application using GWT. So i make these functions in the GWTServiceImpl Class :
public class PageMenuLogin extends FlowPanel {
public PageMenuLogin() {
PageMenuLogin.getService().isSetSession(new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
InlineLabel err=new InlineLabel();
err.setText("Errore Di Connessione");
PageMenuLogin.this.add(err);
}
#Override
public void onSuccess(String result) {
if(result.compareTo("")==0) {
designLogin();
} else {
designLogout(result);
}
}
});
}
public final void designLogin() {
final InlineLabel menu_err=new InlineLabel("");
menu_err.setStyleName("menu_err");
this.add(menu_err);
Button menu_login_button=new Button("Login");
this.add(menu_login_button);
menu_login_button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getService().checkLogin("nickname", "password", new AsyncCallback<Boolean>() {
#Override
public void onFailure(Throwable caught) {
menu_err.setText("Comunicazione Fallita");
}
#Override
public void onSuccess(Boolean result) {
if (result) {
// I LOAD THE PROFILE PAGE
} else {
menu_err.setText("Username e password non validi");
}
}
});
}
});
}
}
********************************************************************************
public class GWTServiceImpl extends RemoteServiceServlet implements GWTService {
HttpServletRequest request;
HttpSession session;
public String isSetSession() {
this.request = this.getThreadLocalRequest();
this.session=this.request.getSession();
if(this.session.getAttribute("nickname")==null) {
return "";
} else {
return (String)this.session.getAttribute("nickname");
}
}
public boolean checkLogin(String username, String password) {
if("i check on the database if the user exist") {
this.session.setAttribute("nickname", value);
return true;
}
return false;
}
}
On client side, i call the GWTServiceImpl functions (server side), i check the return values and i do some operations.
Is this the right way to work with session on GWT? Any suggestion/tips/helps would be appreciated :)
Thanks for your time!!!
EDIT
New GWTServiceImpl :
public class GWTServiceImpl extends RemoteServiceServlet implements GWTService {
HttpSession session;
public String isSetSession() {
HttpSession session=getThreadLocalRequest().getSession();
if(session.getAttribute("nickname")==null) {
return "";
} else {
return (String)session.getAttribute("nickname");
}
}
public boolean checkLogin(String nickname, String password) {
HttpSession session=getThreadLocalRequest().getSession();
Database mydb=Configuration.getDatabase();
mydb.connetti();
// faccio md5 ed escape
String log_check_user=nickname;
String log_check_pass=password;
// controllo che l'utente esista
ArrayList<String[]> db_result=null;
db_result=mydb.selectQuery("SELECT nickname FROM users WHERE nickname='"+log_check_user+"' AND password='"+log_check_pass+"'");
mydb.disconnetti();
if(!db_result.isEmpty()) {
session.setAttribute("nickname", nickname);
return true;
}
return false;
}
public boolean checkLogout() {
HttpSession session=getThreadLocalRequest().getSession();
session.invalidate();
return true;
}
}
Looks like it should work. I do a lot of work with GWT, although I often forego the use of the RemoteServiceServlet in favour of passing data back and forth via JSON.
A few suggestions, though. When you're calling a method or field within the same class, you don't need to include the this keyword. It doesn't hurt, but tends to make your code longer than it needs to be. Feel free to keep it though, if you find it makes things clearer for you.
Also, unless you've got methods that actually use the request, you don't need to create the request object; you can just do
session = getThreadLocalRequest().getSession();
A final suggestion: Since you're using the session in more than one method, it might be a good idea to initialize it right away; So, instead of initializing it in isSetSession(), you could just write HttpSession session = getThreadLocalRequest().getSession();, or initialize it in the class's constructor. As it stands now, if you happen to call checkLogin() before isSetSession(), you'll get a NullPointerException since session hasn't yet been initialized.