go-mocket
go-mocket copied to clipboard
WithReply values getting interchanged during tests
My tests are passing half of the time and failing half of the time when using go-mocket mock and a response struct.
example test:
Describe("GetApplicationStatuses", func() {
Context("on success", func() {
It("should should write inReview and ineligible counts to context", func() {
params := []gin.Param{gin.Param{Key: "company_id", Value: "1"}}
mockContext.Params = params
mockContext.Set("employeeIDs", []string{"1a"})
mockReply := []map[string]interface{}{{"InReview": 1, "Ineligible": 2}}
globalMock.NewMock().
WithQuery("case when app.status in('SUBMITTED','REQUIRES_ACTION')").
WithReply(mockReply)
returnedFunc := GetApplicationStatuses()
returnedFunc(mockContext)
var expectValue = ApplicationStatus{InReview: 1, Ineligible: 2}
Expect(mockContext.Value("Applications")).To(Equal(expectValue))
})
})
failure:
Expected
<middleware.ApplicationStatus>: {InReview: 2, Ineligible: 1}
to equal
<middleware.ApplicationStatus>: {InReview: 1, Ineligible: 2}
func & struct being tested:
func GetApplicationStatuses() gin.HandlerFunc {
return func(c *gin.Context) {
var (
inReview,
ineligible int
applications ApplicationStatus
)
rows, err := db.Table("application as app").
Select("COALESCE(sum(case when app.status in('SUBMITTED','REQUIRES_ACTION') then 1 else 0 end),0) as in_review, "+
"COALESCE(sum(case when app.status = 'INELIGIBLE' then 1 else 0 end),0) as ineligible").
Where("app.id in(select employee.id from employee where employee.x_id in(?))", c.Value("employeeIDs")).
Rows()
if err != nil {
utils.LogError(
fmt.Sprintf("Error getting application statuses: %v", err),
"middleware.GetApplicationStatuses",
)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"message": "Error getting application statuses.",
})
return
}
for rows.Next() {
err := rows.Scan(&inReview, &ineligible)
if err != nil {
utils.LogError(
fmt.Sprintf("Error getting application statuses: %v", err),
"middleware.GetApplicationStatuses",
)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"message": "Error getting application statuses.",
})
return
}
applications = ApplicationStatus{inReview, ineligible}
}
c.Set("Applications", applications)
}
}
// ApplicationStatus struct for response to GetApplicationStatuses
type ApplicationStatus struct {
InReview int `json:"inReview gorm:"column:InReview"`
Ineligible int `json:"ineligible" gorm:"column:Ineligible"`
}
half of the time the test passes fine, the other half it fails because InReview and Ineligible values are swapped. I've been banging my head against the wall with it for a week now. any help would be greatly appreciated. Seems to be happening anytime I'm using a response struct or there is > 1 column on the WithReply. Thanks for a great mocking package btw.
still haven't been able to figure this out, added debugging logs to the test and func, on some occasion rows.Columns() swaps the order of how they should be returned by the query & reply adding test logs with debugs below:
`•••••2018/10/21 14:05:26 Mock Reply: [map[in_review:1 ineligible:2]] 2018/10/21 14:05:26 mock_catcher: check query: SELECT COALESCE(sum(case when app.status in('SUBMITTED','REQUIRES_ACTION') then 1 else 0 end),0) as in_review, COALESCE(sum(case when app.status = 'INELIGIBLE' then 1 else 0 end),0) as ineligible FROM application as app WHERE (app.id in(select employee.id from employee where employee.cs_id in(1a)))
[2018-10-21 14:05:26] [0.05ms] SELECT COALESCE(sum(case when app.status in('SUBMITTED','REQUIRES_ACTION') then 1 else 0 end),0) as in_review, COALESCE(sum(case when app.status = 'INELIGIBLE' then 1 else 0 end),0) as ineligible FROM application as app WHERE (app.id in(select employee.id from employee where employee.cs_id in('1a'))) [0 rows affected or returned ] 2018/10/21 14:05:26 Columns Returned: [ineligible in_review]
• Failure [0.001 seconds] Contrib Middleware GetApplicationStatuses on success [It] should should write inReview and ineligible counts to context
Expected <middleware.ApplicationStatus>: {InReview: 2, Ineligible: 1} to equal <middleware.ApplicationStatus>: {InReview: 1, Ineligible: 2}
Hi @jaylane, let me take look into. I will get back to you as soon as possible.
@Selvatico I also encountered this problem.
I am having the same issue. I am trying to mock replies for two SELECT queries, one count(*) and the other selecting columns (using sql QueryContext and rows.Next() / rows.Scan()). Half of the time the responses get swapped and the test fails.
I am also having the same issue.
I have since switched to: https://github.com/DATA-DOG/go-sqlmock . Appreciate the work put into go-mocket but the Datadog library has much better support.
any movement on this? @saurori does the datadog package support gorm?
@jaylane I'm wondering if go-mocket is looking at how the fields are returned by the DB driver.
In your SELECT statement - you're aliasing the InReview field as in_review
and the Ineligible field as ineligible
Can you try modifying your mock reply as such:
mockReply := []map[string]interface{}{{"in_review": 1, "ineligible": 2}}