github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/delete_test.go (about)

     1  // Copyright 2021 ecodeclub
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package eorm
    16  
    17  import (
    18  	"context"
    19  	"database/sql"
    20  	"errors"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/ecodeclub/eorm/internal/datasource/single"
    25  
    26  	"github.com/ecodeclub/eorm/internal/errs"
    27  
    28  	"github.com/DATA-DOG/go-sqlmock"
    29  	"github.com/stretchr/testify/require"
    30  
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  func TestDeleter_Build(t *testing.T) {
    35  	db := memoryDB()
    36  	testCases := []CommonTestCase{
    37  		{
    38  			name:    "no where",
    39  			builder: NewDeleter[TestModel](db).From(&TestModel{}),
    40  			wantSql: "DELETE FROM `test_model`;",
    41  		},
    42  		{
    43  			name:     "where",
    44  			builder:  NewDeleter[TestModel](db).Where(C("Id").EQ(16)),
    45  			wantSql:  "DELETE FROM `test_model` WHERE `id`=?;",
    46  			wantArgs: []interface{}{16},
    47  		},
    48  		{
    49  			name:    "no where combination",
    50  			builder: NewDeleter[TestCombinedModel](db).From(&TestCombinedModel{}),
    51  			wantSql: "DELETE FROM `test_combined_model`;",
    52  		},
    53  		{
    54  			name:     "where combination",
    55  			builder:  NewDeleter[TestCombinedModel](db).Where(C("CreateTime").EQ(uint64(1000))),
    56  			wantSql:  "DELETE FROM `test_combined_model` WHERE `create_time`=?;",
    57  			wantArgs: []interface{}{uint64(1000)},
    58  		},
    59  	}
    60  
    61  	for _, tc := range testCases {
    62  		c := tc
    63  		t.Run(c.name, func(t *testing.T) {
    64  			query, err := c.builder.Build()
    65  			assert.Equal(t, c.wantErr, err)
    66  			assert.Equal(t, c.wantSql, query.SQL)
    67  			assert.Equal(t, c.wantArgs, query.Args)
    68  		})
    69  	}
    70  }
    71  
    72  func TestDeleter_Exec(t *testing.T) {
    73  	testCases := []struct {
    74  		name      string
    75  		mockOrder func(mock sqlmock.Sqlmock)
    76  		delete    func(*sql.DB, *testing.T) Result
    77  		wantErr   error
    78  		wantVal   sql.Result
    79  	}{
    80  		{
    81  			name: "exec err",
    82  			mockOrder: func(mock sqlmock.Sqlmock) {
    83  				mock.ExpectExec("DELETE FROM `test_model` WHERE `invalid`=").
    84  					WithArgs(1).WillReturnError(errs.NewInvalidFieldError("Invalid"))
    85  			},
    86  			delete: func(db *sql.DB, t *testing.T) Result {
    87  				defer func(db *sql.DB) { _ = db.Close() }(db)
    88  				orm, err := OpenDS("mysql", single.NewDB(db))
    89  				require.NoError(t, err)
    90  				deleter := NewDeleter[TestModel](orm)
    91  				result := deleter.From(&TestModel{}).Where(C("Invalid").EQ(1)).Exec(context.Background())
    92  				return result
    93  			},
    94  			wantErr: errs.NewInvalidFieldError("Invalid"),
    95  		},
    96  		{
    97  			name: "直接删除",
    98  			mockOrder: func(mock sqlmock.Sqlmock) {
    99  				mock.ExpectExec("DELETE FROM `test_model` WHERE `id`=").WithArgs(1).WillReturnResult(sqlmock.NewResult(100, 1000))
   100  			},
   101  			delete: func(db *sql.DB, t *testing.T) Result {
   102  				defer func(db *sql.DB) { _ = db.Close() }(db)
   103  				orm, err := OpenDS("mysql", single.NewDB(db))
   104  				require.NoError(t, err)
   105  				deleter := NewDeleter[TestModel](orm)
   106  				result := deleter.From(&TestModel{}).Where(C("Id").EQ(1)).Exec(context.Background())
   107  				return result
   108  			},
   109  			wantErr: nil,
   110  			wantVal: sqlmock.NewResult(100, 1000),
   111  		},
   112  		{
   113  			name: "事务删除",
   114  			mockOrder: func(mock sqlmock.Sqlmock) {
   115  				mock.ExpectBegin()
   116  				mock.ExpectExec("DELETE FROM `test_model` WHERE `id`=").WithArgs(1).WillReturnResult(sqlmock.NewResult(10, 20))
   117  				mock.ExpectCommit().WillReturnError(errors.New("commit 错误"))
   118  			},
   119  			delete: func(db *sql.DB, t *testing.T) Result {
   120  				defer func(db *sql.DB) { _ = db.Close() }(db)
   121  
   122  				orm, err := OpenDS("mysql", single.NewDB(db))
   123  				require.NoError(t, err)
   124  				tx, err := orm.BeginTx(context.Background(), &sql.TxOptions{})
   125  				require.NoError(t, err)
   126  
   127  				deleter := NewDeleter[TestModel](tx)
   128  				result := deleter.From(&TestModel{}).Where(C("Id").EQ(1)).Exec(context.Background())
   129  				require.NoError(t, result.Err())
   130  
   131  				err = tx.Commit()
   132  				if err != nil {
   133  					return Result{err: err}
   134  				}
   135  				return result
   136  			},
   137  			wantErr: errors.New("commit 错误"),
   138  			wantVal: sqlmock.NewResult(10, 20),
   139  		},
   140  	}
   141  
   142  	for _, tc := range testCases {
   143  		t.Run(tc.name, func(t *testing.T) {
   144  			mockDB, mock, err := sqlmock.New()
   145  			if err != nil {
   146  				t.Fatal(err)
   147  			}
   148  			tc.mockOrder(mock)
   149  			result := tc.delete(mockDB, t)
   150  
   151  			assert.Equal(t, tc.wantErr, result.Err())
   152  
   153  			if result.Err() != nil {
   154  				return
   155  			}
   156  
   157  			rowsAffectedExpect, err := tc.wantVal.RowsAffected()
   158  			require.NoError(t, err)
   159  			rowsAffected, err := result.RowsAffected()
   160  			require.NoError(t, err)
   161  			assert.Equal(t, rowsAffectedExpect, rowsAffected)
   162  
   163  			lastInsertIdExpected, err := tc.wantVal.LastInsertId()
   164  			require.NoError(t, err)
   165  			lastInsertId, err := result.LastInsertId()
   166  			require.NoError(t, err)
   167  			assert.Equal(t, lastInsertIdExpected, lastInsertId)
   168  
   169  			if err = mock.ExpectationsWereMet(); err != nil {
   170  				t.Error(err)
   171  			}
   172  		})
   173  	}
   174  }
   175  
   176  func ExampleDeleter_Build() {
   177  	db := memoryDB()
   178  	query, _ := NewDeleter[TestModel](db).From(&TestModel{}).Build()
   179  	fmt.Printf("SQL: %s", query.SQL)
   180  	// Output:
   181  	// SQL: DELETE FROM `test_model`;
   182  }
   183  
   184  func ExampleDeleter_From() {
   185  	db := memoryDB()
   186  	query, _ := NewDeleter[TestModel](db).From(&TestModel{}).Build()
   187  	fmt.Printf("SQL: %s", query.SQL)
   188  	// Output:
   189  	// SQL: DELETE FROM `test_model`;
   190  }
   191  
   192  func ExampleDeleter_Where() {
   193  	db := memoryDB()
   194  	query, _ := NewDeleter[TestModel](db).Where(C("Id").EQ(12)).Build()
   195  	fmt.Printf("SQL: %s\nArgs: %v", query.SQL, query.Args)
   196  	// Output:
   197  	// SQL: DELETE FROM `test_model` WHERE `id`=?;
   198  	// Args: [12]
   199  }